Golang : Scan forex opportunities by Bollinger bands




My previous post of using Golang to create a scanner to spot opportunities is base on RSI criteria. For this post, we will learn how to scan with another method. We will detect if any given cross breach the upper or lower Bollinger Bands.

Here you go!


 package main

 import (
  "fmt"
  "strconv"
  "strings"
  "time"

  "github.com/awoldes/goanda"
  "github.com/markcheno/go-talib"
 )

 func main() {

  oandaAccountID := ""
  oandaAPIKey := ""

  // set the NewConnection 3rd parameter to [false] to use DEMO account.
  // [true] for LIVE account

  fmt.Println("Starting Oanda Trading bot....")
  UsingLIVEAccount := false // set false to use https://api-fxpractice.oanda.com
  oanda := goanda.NewConnection(oandaAccountID, oandaAPIKey, UsingLIVEAccount)

  temp := "USD_DKK,EUR_AUD,CHF_JPY,EUR_SGD,USD_JPY,EUR_TRY,USD_CZK,GBP_AUD,USD_PLN,USD_SGD,EUR_SEK,USD_HKD,EUR_NZD,SGD_JPY,AUD_CAD,GBP_CHF,USD_THB,TRY_JPY,CHF_HKD,AUD_USD,EUR_DKK,EUR_USD,AUD_NZD,SGD_HKD,EUR_HUF,USD_CNH,EUR_HKD,EUR_JPY,NZD_USD,GBP_PLN,GBP_JPY,USD_TRY,EUR_CAD,USD_SEK,GBP_SGD,EUR_GBP,GBP_HKD,USD_ZAR,AUD_CHF,USD_CHF,USD_MXN,GBP_USD,EUR_CHF,EUR_NOK,AUD_SGD,CAD_CHF,SGD_CHF,CAD_HKD,USD_INR,NZD_CAD,GBP_ZAR,NZD_SGD,ZAR_JPY,CAD_JPY,GBP_CAD,USD_SAR,NZD_CHF,NZD_HKD,GBP_NZD,AUD_HKD,EUR_CZK,CHF_ZAR,USD_HUF,NZD_JPY,HKD_JPY,CAD_SGD,USD_NOK,USD_CAD,AUD_JPY,EUR_PLN,EUR_ZAR"

  // first, clean/remove the comma
  cleaned := strings.Replace(temp, ",", " ", -1)

  // crosses to monitor
  crossesToMonitor := strings.Fields(cleaned)

  fmt.Println("Crosses to monitor : ")
  fmt.Println(crossesToMonitor)

  // Scan by Bollinger Bands
  go ScanCrossByBBands(oanda, crossesToMonitor, 16)
  select {} // this will cause the program to run forever until termination

 }

 //--------------------------------------------------------------------------------------------------------

 func GetPrice(oanda *goanda.OandaConnection, cross string) float64 {
  instrument := cross
  priceResponse := oanda.GetInstrumentPrice(instrument)

  //askPrice := strconv.FormatFloat(priceResponse.Prices[0].Asks[0].Price, 'f', 6, 64)
  //bidPrice := strconv.FormatFloat(priceResponse.Prices[0].Bids[0].Price, 'f', 6, 64)
  //queryTime := priceResponse.Prices[0].Time

  //result := "Asking price at [" + queryTime.String() + "] is " + askPrice + ".Bidding price is " + bidPrice + "."
  //return result

  return priceResponse.Prices[0].Bids[0].Price
 }

 func ScanCrossByBBands(oanda *goanda.OandaConnection, crosses []string, intervalSecond int) {
  counter := time.Tick(time.Duration(intervalSecond) * time.Second) // poll every 16 seconds
  for range counter {
 for k, v := range crosses {

 currentUpper, currentMiddle, currentLower := GetOneHourBBands(oanda, v)

 upperStr := strconv.FormatFloat(currentUpper, 'f', 6, 64) // convert float64 to string
 middleStr := strconv.FormatFloat(currentMiddle, 'f', 6, 64) // convert float64 to string
 lowerStr := strconv.FormatFloat(currentLower, 'f', 6, 64) // convert float64 to string

 fmt.Println(k, v, "Bollinger Bands - Upper : "+upperStr+", Middle(Basis) : "+middleStr+", Lower : "+lowerStr)

 // alert if this particular cross BBands higher or lower than BBands
 currentPrice := GetPrice(oanda, v)
 if currentPrice >= currentUpper {
 currentPriceStr := strconv.FormatFloat(currentUpper, 'f', 6, 64) // convert float64 to string
 fmt.Println(k, v, " price is "+currentPriceStr+" and breached upper band. [**SHORT**]")
 }

 if currentPrice <= currentLower {
 currentPriceStr := strconv.FormatFloat(currentUpper, 'f', 6, 64) // convert float64 to string
 fmt.Println(k, v, " price is "+currentPriceStr+" and breached lower band. [**LONG**]")
 }
 }
  }

 }

 func GetOneHourBBands(oanda *goanda.OandaConnection, cross string) (float64, float64, float64) {

  // See http://developer.oanda.com/rest-live-v20/instrument-ep/#collapse_2_example_curl_1
  // and for the candlestick granularity ... see
  // http://developer.oanda.com/rest-live-v20/instrument-df/#CandlestickGranularity

  // Get 100 candles with 1 hour granularity
  data := oanda.GetCandles(cross, "100", "H1") // H1 = 1 hour
  closeSlice := make([]float64, len(data.Candles))

  // calculate BBands
  for i := 0; i < len(data.Candles); i++ {
 closeSlice[i] = data.Candles[i].Mid.Close
  }

  // source = close, length=20, stddev=2, offset = 0
  upper, middle, lower := talib.BBands(closeSlice, 20, 2.0, 2.0, 0)

  // instead of a slice of values for plotting graph, we only interested in the current value
  return upper[len(upper)-1], middle[len(middle)-1], lower[len(lower)-1]

  // return this if you want to plot graph
  //return talib.BBands(closeSlice, 20, 2, 2, 0)

 }

Sample output:

0 USD_DKK Bollinger Bands - Upper : 6.568570, Middle(Basis) : 6.556630, Lower : 6.544689

1 EUR_AUD Bollinger Bands - Upper : 1.588591, Middle(Basis) : 1.585088, Lower : 1.581585

2 CHF_JPY Bollinger Bands - Upper : 110.766608, Middle(Basis) : 110.600800, Lower : 110.434992

2 CHF_JPY price is 110.766608 and breached lower band. [LONG]

3 EUR_SGD Bollinger Bands - Upper : 1.535802, Middle(Basis) : 1.534125, Lower : 1.532447

4 USD_JPY Bollinger Bands - Upper : 110.841978, Middle(Basis) : 110.617900, Lower : 110.393822

4 USD_JPY price is 110.841978 and breached lower band. [LONG]

5 EUR_TRY Bollinger Bands - Upper : 6.053541, Middle(Basis) : 6.041364, Lower : 6.029188

6 USD_CZK Bollinger Bands - Upper : 22.602139, Middle(Basis) : 22.533306, Lower : 22.464473

7 GBP_AUD Bollinger Bands - Upper : 1.847077, Middle(Basis) : 1.844400, Lower : 1.841723

8 USD_PLN Bollinger Bands - Upper : 3.809006, Middle(Basis) : 3.800306, Lower : 3.791607

9 USD_SGD Bollinger Bands - Upper : 1.349430, Middle(Basis) : 1.348080, Lower : 1.346729

10 EUR_SEK Bollinger Bands - Upper : 10.585036, Middle(Basis) : 10.574920, Lower : 10.564804

11 USD_HKD Bollinger Bands - Upper : 7.849623, Middle(Basis) : 7.849112, Lower : 7.848601

12 EUR_NZD Bollinger Bands - Upper : 1.653353, Middle(Basis) : 1.651515, Lower : 1.649677

13 SGD_JPY Bollinger Bands - Upper : 82.175845, Middle(Basis) : 82.056150, Lower : 81.936455

13 SGD_JPY price is 82.175845 and breached lower band. [LONG]

14 AUD_CAD Bollinger Bands - Upper : 0.947366, Middle(Basis) : 0.946222, Lower : 0.945078

  See also : Golang : Find correlation coefficient example





By Adam Ng(黃武俊)

IF you gain some knowledge or the information here solved your programming problem. Please consider donating to the less fortunate or some charities that you like. Apart from donation, planting trees, volunteering or reducing your carbon footprint will be great too.


Advertisement