func (emaStrategy *EMAStrategy) checkThreshold(tradeType string, EMAdif float64) bool { if tradeType == "buy" { buyThreshold := toFloat(Option["buyThreshold"]) if EMAdif > buyThreshold { logger.Infof("EMAdif(%0.04f) > buyThreshold(%0.04f), trigger to buy\n", EMAdif, buyThreshold) emaStrategy.LessBuyThreshold = false return true } else { if emaStrategy.LessBuyThreshold == false { logger.Infof("cross up, but EMAdif(%0.04f) <= buyThreshold(%0.04f)\n", EMAdif, buyThreshold) emaStrategy.LessBuyThreshold = true } } } else { sellThreshold := toFloat(Option["sellThreshold"]) if sellThreshold > 0 { sellThreshold = -sellThreshold } if EMAdif < sellThreshold { logger.Infof("EMAdif(%0.04f) < sellThreshold(%0.04f), trigger to sell\n", EMAdif, sellThreshold) emaStrategy.LessSellThreshold = false return true } else { if emaStrategy.LessSellThreshold == false { logger.Infof("cross down, but EMAdif(%0.04f) >= sellThreshold(%0.04f)\n", EMAdif, sellThreshold) emaStrategy.LessSellThreshold = true } } } return false }
func RobotWorker() { ticker := time.NewTicker(1 * time.Second) // one second defer ticker.Stop() totalHour, _ := strconv.ParseInt(Option["totalHour"], 0, 64) if totalHour < 1 { totalHour = 1 } fmt.Println("trade robot start working...") go func() { for _ = range ticker.C { peroid, _ := strconv.Atoi(Option["tick_interval"]) strategyName := Option["strategy"] ret := true var records []Record if strategyName != "OPENORDER" { ret, records = marketAPI().GetKLine(peroid) } if ret != false { strategy.Tick(tradeAPI(), records) } } }() logger.Infof("程序将持续运行%d小时后停止", time.Duration(totalHour)) time.Sleep(time.Duration(totalHour) * time.Hour) logger.Infof("程序到达设定时长%d小时,停止运行。", time.Duration(totalHour)) }
// 登录;成功返回用户登录信息(user_login) func Login(username, passwd string) (*model.UserLogin, error) { userLogin := model.NewUserLogin() err := userLogin.Where("username="******" OR email=" + username).Find() if err != nil { logger.Errorf("用户 %s 登录错误:%s", username, err) return nil, errors.New("内部错误,请稍后再试!") } // 校验用户 if userLogin.Uid == 0 { logger.Infof("用户名 %s 不存在", username) return nil, ErrUsername } passcode := userLogin.GetPasscode() md5Passwd := util.Md5(passwd + passcode) logger.Debugf("passwd: %s, passcode: %s, md5passwd: %s, dbpasswd: %s", passwd, passcode, md5Passwd, userLogin.Passwd) if md5Passwd != userLogin.Passwd { logger.Infof("用户名 %s 填写的密码错误", username) return nil, ErrPasswd } // 登录,活跃度+1 go IncUserWeight("uid="+strconv.Itoa(userLogin.Uid), 1) return userLogin, nil }
func RobotWorker() { fmt.Println("env", Config["env"]) if Config["env"] == "dev" { fmt.Println("test working...") var tradeAPI common.TradeAPI tradeAPI = huobi.NewHuobi() tradeAPI.Get_account_info() symbol := "btc_cny" tradeAPI.GetOrderBook(symbol) //testHuobiAPI() //testOkcoinLTCAPI() return } ticker := time.NewTicker(2 * time.Second) //2s defer ticker.Stop() var tradeAPI common.TradeAPI tradeAPI = huobi.NewHuobi() tradeAPI.Get_account_info() tradeAPI = okcoin.NewOkcoin() tradeAPI.Get_account_info() if Option["tradecenter"] == "huobi" { tradeAPI = huobi.NewHuobi() } else if Option["tradecenter"] == "okcoin" { tradeAPI = okcoin.NewOkcoin() } else { logger.Fatalln("Please config the tradecenter firstly...") return } peroid, _ := strconv.Atoi(Option["tick_interval"]) totalHour, _ := strconv.ParseInt(Option["totalHour"], 0, 64) if totalHour < 1 { totalHour = 1 } fmt.Println("robot working...") go func() { for _ = range ticker.C { tradeAPI.AnalyzeKLine(peroid) } }() logger.Infof("程序将持续运行%d小时后停止", time.Duration(totalHour)) time.Sleep(time.Duration(totalHour) * time.Hour) logger.Infof("程序到达设定时长%d小时,停止运行。", time.Duration(totalHour)) }
func RobotWorker() { fmt.Println("env", Config["env"]) if DebugEnv || Config["env"] == "dev" { fmt.Println("test working...") // var tradeAPI TradeAPI // tradeAPI = okcoin.NewOkcoin() // tradeAPI.GetAccount() // tradeAPI.GetOrderBook() // tradeAPI = huobi.NewHuobi() // accout_info, ret := tradeAPI.GetAccount() // fmt.Println(ret, accout_info) // ret, orderbook := tradeAPI.GetOrderBook() // fmt.Println(ret, orderbook) testHuobiAPI() //testOkcoinLTCAPI() return } ticker := time.NewTicker(8 * time.Second) //2s defer ticker.Stop() totalHour, _ := strconv.ParseInt(Option["totalHour"], 0, 64) if totalHour < 1 { totalHour = 1 } fmt.Println("robot working...") go func() { for _ = range ticker.C { records := []Record{} strategy.Tick(tradeAPI(), records) // peroid, _ := strconv.Atoi(Option["tick_interval"]) // ret, records := marketAPI().GetKLine(peroid) // if ret != false { // strategy.Tick(tradeAPI(), records) // } } }() logger.Infof("程序将持续运行%d小时后停止", time.Duration(totalHour)) time.Sleep(time.Duration(totalHour) * time.Hour) logger.Infof("程序到达设定时长%d小时,停止运行。", time.Duration(totalHour)) }
func RobotWorker() { fmt.Println("env", Config["env"]) if DebugEnv || Config["env"] == "dev" { fmt.Println("test working...") var tradeAPI TradeAPI tradeAPI = okcoin.NewOkcoin() tradeAPI.GetAccount() tradeAPI.GetOrderBook() tradeAPI = huobi.NewHuobi() tradeAPI.GetAccount() ret, orderbook := tradeAPI.GetOrderBook() fmt.Println(ret, orderbook) //testHuobiAPI() //testOkcoinLTCAPI() return } ticker := time.NewTicker(1 * time.Second) //2s defer ticker.Stop() totalHour, _ := strconv.ParseInt(Option["totalHour"], 0, 64) if totalHour < 1 { totalHour = 1 } fmt.Println("robot working...") go func() { for _ = range ticker.C { peroid, _ := strconv.Atoi(Option["tick_interval"]) strategyName := Option["strategy"] ret := true var records []Record if strategyName != "OPENORDER" { ret, records = marketAPI().GetKLine(peroid) } if ret != false { strategy.Tick(tradeAPI(), records) } } }() logger.Infof("程序将持续运行%d小时后停止", time.Duration(totalHour)) time.Sleep(time.Duration(totalHour) * time.Hour) logger.Infof("程序到达设定时长%d小时,停止运行。", time.Duration(totalHour)) }
// the3crow strategy func (the3crow *the3crowStrategy) Tick(records []Record) bool { if the3crow.PrevClosePrice == lastPrice { return false } the3crow.PrevClosePrice = lastPrice logger.Infof("lastPrice %0.02f\n", lastPrice) logger.Infof("3 open %0.02f close %0.02f\n", records[length-2].Open, records[length-2].Close) logger.Infof("2 open %0.02f close %0.02f\n", records[length-3].Open, records[length-3].Close) logger.Infof("1 open %0.02f close %0.02f\n", records[length-4].Open, records[length-4].Close) if records[length-2].Close > records[length-2].Open { logger.Infof("3阳") } else { logger.Infof("3阴") } if records[length-3].Close > records[length-3].Open { logger.Infof("2阳") } else { logger.Infof("2阴") } if records[length-4].Close > records[length-4].Open { logger.Infof("1阳") } else { logger.Infof("1阴") } logger.Infoln("---------") // the3crow cross if records[length-2].Close > records[length-2].Open && records[length-3].Close > records[length-3].Open && records[length-4].Close > records[length-4].Open { Buy() } else if records[length-2].Close < records[length-2].Open && records[length-3].Close < records[length-3].Open && records[length-4].Close < records[length-4].Open { Sell() } // do sell when price is below stoploss point processStoploss(lastPrice) processTimeout() return true }
func (w Okcoin) GetAccount() (account Account, ret bool) { tradeAPI := NewOkcoinTrade(SecretOption["ok_partner"], SecretOption["ok_secret_key"]) userInfo, ret := tradeAPI.GetAccount() logger.Infoln("account:", userInfo) if !ret { logger.Traceln("okcoin GetAccount failed") return } else { logger.Traceln(userInfo) account.Available_cny = userInfo.Info.Funds.Free.CNY account.Available_btc = userInfo.Info.Funds.Free.BTC account.Available_ltc = userInfo.Info.Funds.Free.LTC account.Frozen_cny = userInfo.Info.Funds.Freezed.CNY account.Frozen_btc = userInfo.Info.Funds.Freezed.BTC account.Frozen_ltc = userInfo.Info.Funds.Freezed.LTC logger.Infof("okcoin资产: \n 可用cny:%-10s \tbtc:%-10s \tltc:%-10s \n 冻结cny:%-10s \tbtc:%-10s \tltc:%-10s\n", account.Available_cny, account.Available_btc, account.Available_ltc, account.Frozen_cny, account.Frozen_btc, account.Frozen_ltc) //logger.Infoln(Account) return } }
func (w Okcoin) GetAccount() (account Account, ret bool) { tradeAPI := w.tradeAPI userInfo, ret := tradeAPI.GetAccount() if !ret { logger.Traceln("okcoin GetAccount failed") return } else { logger.Traceln(userInfo) account.Available_cny = userInfo.Info.Funds.Free.CNY account.Available_btc = userInfo.Info.Funds.Free.BTC account.Available_ltc = userInfo.Info.Funds.Free.LTC account.Frozen_cny = userInfo.Info.Funds.Freezed.CNY account.Frozen_btc = userInfo.Info.Funds.Freezed.BTC account.Frozen_ltc = userInfo.Info.Funds.Freezed.LTC logger.Infof("okcoin资产: \n 可用cny:%-10s \tbtc:%-10s \tltc:%-10s \n 冻结cny:%-10s \tbtc:%-10s \tltc:%-10s\n", account.Available_cny, account.Available_btc, account.Available_ltc, account.Frozen_cny, account.Frozen_btc, account.Frozen_ltc) return } }
func (w Okcoin) Get_account_info() (userMoney common.UserMoney, ret bool) { tradeAPI := NewOkcoinTrade(SecretOption["ok_partner"], SecretOption["ok_secret_key"]) userInfo, ret := tradeAPI.Get_account_info() if !ret { logger.Traceln("okcoin Get_account_info failed") return } else { logger.Traceln(userInfo) userMoney.Available_cny = userInfo.Info.Funds.Free.CNY userMoney.Available_btc = userInfo.Info.Funds.Free.BTC userMoney.Available_ltc = userInfo.Info.Funds.Free.LTC userMoney.Frozen_cny = userInfo.Info.Funds.Freezed.CNY userMoney.Frozen_btc = userInfo.Info.Funds.Freezed.BTC userMoney.Frozen_ltc = userInfo.Info.Funds.Freezed.LTC logger.Infof("okcoin资产: \n 可用cny:%-10s \tbtc:%-10s \tltc:%-10s \n 冻结cny:%-10s \tbtc:%-10s \tltc:%-10s\n", userMoney.Available_cny, userMoney.Available_btc, userMoney.Available_ltc, userMoney.Frozen_cny, userMoney.Frozen_btc, userMoney.Frozen_ltc) //logger.Infoln(userMoney) return } }
func (w Huobi) Get_account_info() (userMoney common.UserMoney, ret bool) { tradeAPI := NewHuobiTrade(SecretOption["huobi_access_key"], SecretOption["huobi_secret_key"]) userInfo, ret := tradeAPI.Get_account_info() if !ret { logger.Traceln("Huobi Get_account_info failed") return } else { userMoney.Available_cny = userInfo.Available_cny_display userMoney.Available_btc = userInfo.Available_btc_display userMoney.Available_ltc = "N/A" userMoney.Frozen_cny = userInfo.Frozen_cny_display userMoney.Frozen_btc = userInfo.Frozen_btc_display userMoney.Frozen_ltc = "N/A" logger.Infof("Huobi资产: \n 可用cny:%-10s \tbtc:%-10s \tltc:%-10s \n 冻结cny:%-10s \tbtc:%-10s \tltc:%-10s\n", userMoney.Available_cny, userMoney.Available_btc, userMoney.Available_ltc, userMoney.Frozen_cny, userMoney.Frozen_btc, userMoney.Frozen_ltc) return } }
func (w Bitvc) GetAccount() (account Account, ret bool) { tradeAPI := NewBitvcTrade(SecretOption["huobi_access_key"], SecretOption["huobi_secret_key"]) userInfo, ret := tradeAPI.GetAccount() if !ret { logger.Traceln("Bitvc GetAccount failed") return } else { account.Available_cny = userInfo.Available_cny_display account.Available_btc = userInfo.Available_btc_display account.Available_ltc = "N/A" account.Frozen_cny = userInfo.Frozen_cny_display account.Frozen_btc = userInfo.Frozen_btc_display account.Frozen_ltc = "N/A" logger.Infof("Bitvc资产: \n 可用cny:%-10s \tbtc:%-10s \tltc:%-10s \n 冻结cny:%-10s \tbtc:%-10s \tltc:%-10s\n", account.Available_cny, account.Available_btc, account.Available_ltc, account.Frozen_cny, account.Frozen_btc, account.Frozen_ltc) return } }
//circular strategy func (circular *circularStrategy) Tick(records []Record) bool { if circular.PrevClosePrice == lastPrice { return false } basePrice, err := strconv.ParseFloat(Option["basePrice"], 64) if err != nil { logger.Debugln("config item basePrice is not float") return false } fluctuation, err := strconv.ParseFloat(Option["fluctuation"], 64) if err != nil { logger.Debugln("config item fluctuation is not float") return false } circular.PrevClosePrice = lastPrice logger.Infof("lastPrice %0.02f\n", lastPrice) if lastPrice >= basePrice+fluctuation { Sell() } else if lastPrice <= basePrice-fluctuation { Buy() } //do sell when price is below stoploss point processStoploss(lastPrice) processTimeout() return true }
func (w *Huobi) AnalyzePeroidLine(filename string, content string) bool { //logger.Infoln(content) //logger.Infoln(filename) PeroidRecords := ParsePeroidCSV(filename) var xData []string var yData []float64 for _, v := range PeroidRecords { xData = append(xData, v.Date+" "+v.Time) yData = append(yData, v.Close) //yData = append(yData, (v.Close+v.Open+v.High+v.Low)/4.0) //yData = append(yData, v.Low) } w.xData = xData w.yData = yData //rsi(yData) if Config["env"] == "test" { w.do2Percent(xData, yData) return true k, d, j := doKDJ(PeroidRecords) length := len(k) // Loop through the entire array. for i := 0; i < length; i++ { logger.Infof("[%s-%s]%d/%d/%d\n", PeroidRecords[i].Date, PeroidRecords[i].Time, int(k[i]), int(d[i]), int(j[i])) } } else { w.doEMA(xData, yData) return true } return true }
func (w Peatio) GetAccount() (account Account, ret bool) { tradeAPI, _ := newPeatio(SecretOption["peatio_access_key"], SecretOption["peatio_secret_key"], "btc", 0) userInfo, err := tradeAPI.GetAccount() if err != nil { logger.Traceln("Peatio GetAccount failed") ret = false return } else { ret = true account.Available_cny = float2str(userInfo.Balance) account.Available_btc = float2str(userInfo.Stocks) account.Available_ltc = "N/A" account.Frozen_cny = float2str(userInfo.FrozenBalance) account.Frozen_btc = float2str(userInfo.FrozenStocks) account.Frozen_ltc = "N/A" logger.Infof("Peatio资产: \n 可用cny:%-10s \tbtc:%-10s \tltc:%-10s \n 冻结cny:%-10s \tbtc:%-10s \tltc:%-10s\n", account.Available_cny, account.Available_btc, account.Available_ltc, account.Frozen_cny, account.Frozen_btc, account.Frozen_ltc) return } }
// 获取当前登录用户信息(常用信息) func FindCurrentUser(username string) (user map[string]interface{}, err error) { userLogin := model.NewUserLogin() err = userLogin.Where("username="******"获取用户 %s 信息失败:%s", username, err) return } if userLogin.Uid == 0 { logger.Infof("用户 %s 不存在!", username) return } user = map[string]interface{}{ "uid": userLogin.Uid, "username": userLogin.Username, "email": userLogin.Email, } // 获取未读消息数 user["msgnum"] = FindNotReadMsgNum(userLogin.Uid) // 获取角色信息 userRoleList, err := model.NewUserRole().Where("uid=" + strconv.Itoa(userLogin.Uid)).FindAll() if err != nil { logger.Errorf("获取用户 %s 角色 信息失败:%s", username, err) return } for _, userRole := range userRoleList { if userRole.Roleid <= model.AdminMinRoleId { // 是管理员 user["isadmin"] = true } } return }
// MACD strategy func (macdStrategy *MACDStrategy) Tick(records []Record) bool { // read config shortEMA, _ := strconv.Atoi(Option["shortEMA"]) longEMA, _ := strconv.Atoi(Option["longEMA"]) signalPeriod, _ := strconv.Atoi(Option["signalPeriod"]) /* MACDMinThreshold, err := strconv.ParseFloat(Option["MACDMinThreshold"], 64) if err != nil { logger.Debugln("config item MACDMinThreshold is not float") return false } */ MACDbuyThreshold, err := strconv.ParseFloat(Option["MACDbuyThreshold"], 64) if err != nil { logger.Errorln("config item MACDbuyThreshold is not float") return false } MACDsellThreshold, err := strconv.ParseFloat(Option["MACDsellThreshold"], 64) if err != nil { logger.Errorln("config item MACDsellThreshold is not float") return false } var Price []float64 for _, v := range records { Price = append(Price, v.Close) } // compute the indictor emaShort := EMA(Price, shortEMA) emaLong := EMA(Price, longEMA) MACDdif := getMACDdif(emaShort, emaLong) MACDSignal := getMACDSignal(MACDdif, signalPeriod) MACDHistogram := getMACDHistogram(MACDdif, MACDSignal) if MACDdif[length-1] != macdStrategy.PrevMACDdif { macdStrategy.PrevMACDdif = MACDdif[length-1] logger.Infof("MACD:d%5.03f\ts%5.03f\tph%5.03f\th%5.03f\tPrice:%5.02f\n", MACDdif[length-1], MACDSignal[length-1], MACDHistogram[length-2], MACDHistogram[length-1], Price[length-1]) } // macd cross if (MACDHistogram[length-2] < -0.000001 && MACDHistogram[length-1] > MACDbuyThreshold) || (PrevTrade == "sell" && MACDHistogram[length-2] > 0.000001 && MACDHistogram[length-1] > MACDbuyThreshold) { Buy() } else if (MACDHistogram[length-2] > 0.000001 && MACDHistogram[length-1] < MACDsellThreshold) || (PrevTrade == "buy" && MACDHistogram[length-2] < -0.000001 && MACDHistogram[length-1] < MACDsellThreshold) { Sell() } // do sell when price is below stoploss point processStoploss(lastPrice) processTimeout() return true }
func (emaStrategy *EMAStrategy) checkThreshold(direction string, EMAdif float64) bool { if direction == "buy" { buyThreshold, err := strconv.ParseFloat(Option["buyThreshold"], 64) if err != nil { logger.Errorln("config item buyThreshold is not float") return false } if EMAdif > buyThreshold { logger.Infof("EMAdif(%0.04f) > buyThreshold(%0.04f), trigger to buy\n", EMAdif, buyThreshold) emaStrategy.LessBuyThreshold = false return true } else { if emaStrategy.LessBuyThreshold == false { logger.Infof("cross up, but EMAdif(%0.04f) <= buyThreshold(%0.04f)\n", EMAdif, buyThreshold) emaStrategy.LessBuyThreshold = true } } } else { sellThreshold, err := strconv.ParseFloat(Option["sellThreshold"], 64) if err != nil { logger.Errorln("config item sellThreshold is not float") return false } if sellThreshold > 0 { sellThreshold = -sellThreshold } if EMAdif < sellThreshold { logger.Infof("EMAdif(%0.04f) < sellThreshold(%0.04f), trigger to sell\n", EMAdif, sellThreshold) emaStrategy.LessSellThreshold = false return true } else { if emaStrategy.LessSellThreshold == false { logger.Infof("cross down, but EMAdif(%0.04f) >= sellThreshold(%0.04f)\n", EMAdif, sellThreshold) emaStrategy.LessSellThreshold = true } } } return false }
//kdjStrategy strategy func (kdjStrategy *KDJStrategy) Tick(records []Record) bool { if kdjStrategy.PrevTime == records[length-1].TimeStr && kdjStrategy.PrevPrice == lastPrice { return false } //K线为白,D线为黄,J线为红,K in middle k, d, j := getKDJ(records) if kdjStrategy.PrevTime != records[length-1].TimeStr || kdjStrategy.PrevPrice != records[length-1].Close { kdjStrategy.PrevTime = records[length-1].TimeStr kdjStrategy.PrevPrice = lastPrice logger.Infoln(records[length-1].TimeStr, records[length-1].Close) logger.Infof("d(黄线)%0.0f\tk(白线)%0.0f\tj(红线)%0.0f\n", d[length-2], k[length-2], j[length-2]) logger.Infof("d(黄线)%0.0f\tk(白线)%0.0f\tj(红线)%0.0f\n", d[length-1], k[length-1], j[length-1]) } if ((j[length-2] < k[length-2] && k[length-2] < d[length-2]) || PrevTrade == "sell") && (j[length-1] > k[length-1] && k[length-1] > d[length-1]) { logger.Infoln("KDJ up cross") if d[length-2] <= 30 { Buy() } } if ((j[length-2] > k[length-2] && k[length-2] > d[length-2]) || PrevTrade == "buy") && (j[length-1] < k[length-1] && k[length-1] < d[length-1]) { logger.Infoln("KDJ down cross") if d[length-2] >= 70 { Sell() } } //do sell when price is below stoploss point processStoploss(lastPrice) processTimeout() return true }
func marketAPI() (marketAPI MarketAPI) { logger.Infof(Option["datacenter"]) if Option["datacenter"] == "huobi" { marketAPI = huobi.NewHuobi() } else if Option["datacenter"] == "okcoin" { marketAPI = okcoin.NewOkcoin() } else if Option["datacenter"] == "peatio" { marketAPI = peatio.NewPeatio() } else if Option["datacenter"] == "bittrex" { marketAPI = Bittrex.Manager() } else { logger.Fatalln("Please config the market center...") panic(-1) } return }
//HLCross strategy func (HLCross *HLCrossStrategy) Tick(records []Record) bool { //read config shortEMA, _ := strconv.Atoi(Option["shortEMA"]) var Price []float64 for _, v := range records { Price = append(Price, v.Close) } //compute the indictor emaShort := EMA(Price, shortEMA) if HLCross.PrevClosePrice != records[length-1].Close || HLCross.PrevHighPrice != records[length-2].High || HLCross.PrevLowPrice != records[length-2].Low { HLCross.PrevClosePrice = records[length-1].Close HLCross.PrevHighPrice = records[length-2].High HLCross.PrevLowPrice = records[length-2].Low logger.Infof("lastPrice %0.02f prevHigh %0.02f prevLow %0.02f\n", lastPrice, records[length-2].High, records[length-2].Low) } //HLCross cross if Price[length-2] > emaShort[length-2] && records[length-2].Volumn > 500 && records[length-2].High > records[length-3].High && records[length-2].Low > records[length-3].Low { Buy() } else if Price[length-2] < emaShort[length-2] && (records[length-2].High < records[length-3].High || records[length-2].Low < records[length-3].Low) { Sell() } //do sell when price is below stoploss point processStoploss(lastPrice) processTimeout() return true }
func testKLineAPI(done chan bool) { ticker := time.NewTicker(2000 * time.Millisecond) //2s huobi := huobiapi.NewHuobi() huobi.Peroid, _ = strconv.Atoi(Option["tick_interval"]) totalHour, _ := strconv.ParseInt(Option["totalHour"], 0, 64) if totalHour < 1 { totalHour = 1 } slippage, err := strconv.ParseFloat(Config["slippage"], 64) if err != nil { logger.Debugln("config item slippage is not float") slippage = 0 } huobi.Slippage = slippage huobi.Disable_trading = 0 go func() { for _ = range ticker.C { if huobi.Peroid == 1 { huobi.TradeKLineMinute() } else { huobi.TradeKLinePeroid(huobi.Peroid) } } }() oneHour := 60 * 60 * 1000 * time.Millisecond logger.Infof("程序将持续运行%d小时后停止", time.Duration(totalHour)) time.Sleep(time.Duration(totalHour) * oneHour) ticker.Stop() fmt.Println("程序到达设定时长%d小时,停止运行。", time.Duration(totalHour)) done <- true }
func (w *Huobi) AnalyzePeroidLine(filename string, content string) bool { //logger.Infoln(content) //logger.Infoln(filename) PeroidRecords := ParsePeroidCSV(filename) var Time []string var Price []float64 var Volumn []float64 for _, v := range PeroidRecords { Time = append(Time, v.Date+" "+v.Time) Price = append(Price, v.Close) Volumn = append(Volumn, v.Volumn) //Price = append(Price, (v.Close+v.Open+v.High+v.Low)/4.0) //Price = append(Price, v.Low) } w.Time = Time w.Price = Price w.Volumn = Volumn //rsi(Price) if Config["env"] == "test" { w.do2Percent(Time, Price) return true k, d, j := doKDJ(PeroidRecords) length := len(k) // Loop through the entire array. for i := 0; i < length; i++ { logger.Infof("[%s-%s]%d/%d/%d\n", PeroidRecords[i].Date, PeroidRecords[i].Time, int(k[i]), int(d[i]), int(j[i])) } } else { w.doEMA(Time, Price, Volumn) return true } return true }
//EMA strategy func (emamacdemaStrategy *EMAMACDEMAStrategy) Tick(records []Record) bool { //read config shortEMA, _ := strconv.Atoi(Option["shortEMA"]) longEMA, _ := strconv.Atoi(Option["longEMA"]) signalPeriod, _ := strconv.Atoi(Option["signalPeriod"]) nTradeAmount, err := strconv.ParseFloat(Option["tradeAmount"], 64) if err != nil { logger.Errorln("config item tradeAmount is not float") return false } MacdTradeAmount := fmt.Sprintf("%0.02f", 0.5*nTradeAmount) tradeAmount := Option["tradeAmount"] stoploss, err := strconv.ParseFloat(Option["stoploss"], 64) if err != nil { logger.Errorln("config item stoploss is not float") return false } MACDbuyThreshold, err := strconv.ParseFloat(Option["MACDbuyThreshold"], 64) if err != nil { logger.Errorln("config item MACDbuyThreshold is not float") return false } MACDsellThreshold, err := strconv.ParseFloat(Option["MACDsellThreshold"], 64) if err != nil { logger.Errorln("config item MACDsellThreshold is not float") return false } var Time []string var Price []float64 var Volumn []float64 for _, v := range records { Time = append(Time, v.TimeStr) Price = append(Price, v.Close) Volumn = append(Volumn, v.Volumn) //Price = append(Price, (v.Close+v.Open+v.High+v.Low)/4.0) //Price = append(Price, v.Low) } //compute the indictor emaShort := EMA(Price, shortEMA) emaLong := EMA(Price, longEMA) EMAdif := getMACDdif(emaShort, emaLong) MACDdif := getMACDdif(emaShort, emaLong) MACDSignal := getMACDSignal(MACDdif, signalPeriod) MACDHistogram := getMACDHistogram(MACDdif, MACDSignal) length := len(Price) if emamacdemaStrategy.PrevEMACross == "unknown" { if is_uptrend(EMAdif[length-3]) { emamacdemaStrategy.PrevEMACross = "up" } else if is_downtrend(EMAdif[length-3]) { emamacdemaStrategy.PrevEMACross = "down" } else { emamacdemaStrategy.PrevEMACross = "unknown" } logger.Infoln("prev cross is", emamacdemaStrategy.PrevEMACross) if is_uptrend(EMAdif[length-3]) { logger.Infoln("上一个趋势是上涨,等待卖出点触发") } else if is_downtrend(EMAdif[length-3]) { logger.Infoln("上一个趋势是下跌,等待买入点触发") } else { logger.Infoln("上一个趋势是unknown。。。") } } if EMAdif[length-1] != emamacdemaStrategy.PrevEMAdif { emamacdemaStrategy.PrevEMAdif = EMAdif[length-1] logger.Infof("EMA [%0.02f,%0.02f,%0.02f] Diff:%0.03f\t%0.03f\n", Price[length-1], emaShort[length-1], emaLong[length-1], EMAdif[length-2], EMAdif[length-1]) } if MACDdif[length-1] != emamacdemaStrategy.PrevMACDdif { emamacdemaStrategy.PrevMACDdif = MACDdif[length-1] logger.Infof("MACD:d=%5.03f\ts=%5.03f\th=%5.03f\tpre-h=%5.03f\n", MACDdif[length-1], MACDSignal[length-1], MACDHistogram[length-1], MACDHistogram[length-2]) } //reset LessBuyThreshold LessSellThreshold flag when (^ or V) happen if emamacdemaStrategy.LessBuyThreshold && is_downtrend(EMAdif[length-1]) { emamacdemaStrategy.LessBuyThreshold = false emamacdemaStrategy.PrevEMACross = "down" //reset logger.Infoln("down->up(EMA diff < buy threshold)->down ^") } if emamacdemaStrategy.LessSellThreshold && is_uptrend(EMAdif[length-1]) { emamacdemaStrategy.LessSellThreshold = false emamacdemaStrategy.PrevEMACross = "up" //reset logger.Infoln("up->down(EMA diff > sell threshold)->up V") } //EMA cross if (emamacdemaStrategy.is_upcross(EMAdif[length-2], EMAdif[length-1]) || emamacdemaStrategy.LessBuyThreshold) || (emamacdemaStrategy.is_downcross(EMAdif[length-2], EMAdif[length-1]) || emamacdemaStrategy.LessSellThreshold) { //up cross //do buy when cross up if emamacdemaStrategy.is_upcross(EMAdif[length-2], EMAdif[length-1]) || emamacdemaStrategy.LessBuyThreshold { if Option["enable_trading"] == "1" && emamacdemaStrategy.PrevEMATrade != "buy" { emamacdemaStrategy.PrevEMACross = "up" if emamacdemaStrategy.checkThreshold("buy", EMAdif[length-1]) { emamacdemaStrategy.PrevEMATrade = "buy" diff := fmt.Sprintf("%0.03f", EMAdif[length-1]) warning := "EMA up cross, 买入buy In<----市价" + getTradePrice("", Price[length-1]) + ",委托价" + getTradePrice("buy", Price[length-1]) + ",diff" + diff logger.Infoln(warning) if buy(getTradePrice("buy", Price[length-1]), tradeAmount) != "0" { emamacdemaStrategy.PrevBuyPirce = Price[length-1] warning += "[委托成功]" } else { warning += "[委托失败]" } go email.TriggerTrender(warning) } } } //do sell when cross down if emamacdemaStrategy.is_downcross(EMAdif[length-2], EMAdif[length-1]) || emamacdemaStrategy.LessSellThreshold { emamacdemaStrategy.PrevEMACross = "down" if Option["enable_trading"] == "1" && emamacdemaStrategy.PrevEMATrade != "sell" { if emamacdemaStrategy.checkThreshold("sell", EMAdif[length-1]) { emamacdemaStrategy.PrevEMATrade = "sell" diff := fmt.Sprintf("%0.03f", EMAdif[length-1]) warning := "EMA down cross, 卖出Sell Out---->市价" + getTradePrice("", Price[length-1]) + ",委托价" + getTradePrice("sell", Price[length-1]) + ",diff" + diff logger.Infoln(warning) var ematradeAmount string if emamacdemaStrategy.PrevMACDTrade == "sell" { ematradeAmount = MacdTradeAmount emamacdemaStrategy.PrevMACDTrade = "init" } else { ematradeAmount = tradeAmount } if sell(getTradePrice("sell", Price[length-1]), ematradeAmount) != "0" { warning += "[委托成功]" } else { warning += "[委托失败]" } go email.TriggerTrender(warning) } } } //backup the kline data for analyze if Config["env"] == "dev" { backup(Time[length-1]) } } //macd cross if MACDdif[length-1] > 0 { if (MACDHistogram[length-2] < -0.000001 && MACDHistogram[length-1] > MACDbuyThreshold) || (emamacdemaStrategy.PrevMACDTrade == "sell" && MACDHistogram[length-2] > 0.000001 && MACDHistogram[length-1] > MACDbuyThreshold) { if Option["enable_trading"] == "1" && emamacdemaStrategy.PrevMACDTrade == "sell" { emamacdemaStrategy.PrevMACDTrade = "buy" histogram := fmt.Sprintf("%0.03f", MACDHistogram[length-1]) warning := "MACD up cross, 买入buy In<----市价" + getTradePrice("", Price[length-1]) + ",委托价" + getTradePrice("buy", Price[length-1]) + ",histogram" + histogram logger.Infoln(warning) if buy(getTradePrice("buy", Price[length-1]), MacdTradeAmount) != "0" { emamacdemaStrategy.PrevBuyPirce = Price[length-1] warning += "[委托成功]" } else { warning += "[委托失败]" } go email.TriggerTrender(warning) } } else if (Price[length-1] < emaLong[length-1]) && ((MACDHistogram[length-2] > 0.000001 && MACDHistogram[length-1] < MACDsellThreshold) || (emamacdemaStrategy.PrevMACDTrade == "buy" && MACDHistogram[length-2] < -0.000001 && MACDHistogram[length-1] < MACDsellThreshold)) { if Option["enable_trading"] == "1" && emamacdemaStrategy.PrevMACDTrade != "sell" { emamacdemaStrategy.PrevMACDTrade = "sell" histogram := fmt.Sprintf("%0.03f", MACDHistogram[length-1]) warning := "MACD down cross, 卖出Sell Out---->市价" + getTradePrice("", Price[length-1]) + ",委托价" + getTradePrice("sell", Price[length-1]) + ",histogram" + histogram logger.Infoln(warning) if sell(getTradePrice("sell", Price[length-1]), MacdTradeAmount) != "0" { warning += "[委托成功]" } else { warning += "[委托失败]" } go email.TriggerTrender(warning) } } } //do sell when price is below stoploss point if Price[length-1] < emamacdemaStrategy.PrevBuyPirce*(1-stoploss*0.01) { if Option["enable_trading"] == "1" && emamacdemaStrategy.PrevEMATrade != "sell" { warning := "stop loss, 卖出Sell Out---->市价" + getTradePrice("", Price[length-1]) + ",委托价" + getTradePrice("sell", Price[length-1]) logger.Infoln(warning) var ematradeAmount string if emamacdemaStrategy.PrevMACDTrade == "sell" { ematradeAmount = MacdTradeAmount } else { ematradeAmount = tradeAmount } if sell(getTradePrice("sell", Price[length-1]), ematradeAmount) != "0" { warning += "[委托成功]" } else { warning += "[委托失败]" } go email.TriggerTrender(warning) emamacdemaStrategy.PrevEMATrade = "sell" emamacdemaStrategy.PrevMACDTrade = "init" emamacdemaStrategy.PrevBuyPirce = 0 } } return true }
//KDJ-EX strategy func (oo *OOStrategy) Tick(records []Record) bool { const btcslap = 0.2 const ltcslap = 0.01 const timeout = 20 const ordercount = 1 numTradeAmount, err := strconv.ParseFloat(Option["tradeAmount"], 64) if err != nil { logger.Errorln("config item tradeAmount is not float") return false } nSplitTradeAmount := numTradeAmount / float64(ordercount) splitTradeAmount := fmt.Sprintf("%f", nSplitTradeAmount) var Time []string var Price []float64 var Volumn []float64 for _, v := range records { Time = append(Time, v.TimeStr) Price = append(Price, v.Close) Volumn = append(Volumn, v.Volumn) //Price = append(Price, (v.Close+v.Open+v.High+v.Low)/4.0) //Price = append(Price, v.Low) } //K线为白,D线为黄,J线为红,K in middle k, d, j := getKDJ(records) length := len(records) if oo.PrevTime != records[length-1].TimeStr || oo.PrevPrice != records[length-1].Close { oo.PrevTime = records[length-1].TimeStr oo.PrevPrice = records[length-1].Close logger.Infoln(records[length-1].TimeStr, records[length-1].Close) logger.Infof("d(黄线)%0.0f\tk(白线)%0.0f\tj(红线)%0.0f\n", d[length-2], k[length-2], j[length-2]) logger.Infof("d(黄线)%0.0f\tk(白线)%0.0f\tj(红线)%0.0f\n", d[length-1], k[length-1], j[length-1]) } if ((j[length-2] < k[length-2] && k[length-2] < d[length-2]) || oo.PrevKDJTrade == "sell") && (j[length-1] > k[length-1] && k[length-1] > d[length-1]) { logger.Infoln("KDJ up cross") oo.PrevKDJTrade = "buy" } if ((j[length-2] > k[length-2] && k[length-2] > d[length-2]) || oo.PrevKDJTrade == "buy") && (j[length-1] < k[length-1] && k[length-1] < d[length-1]) { logger.Infoln("KDJ down cross") oo.PrevKDJTrade = "sell" } if oo.PrevKDJTrade == "sell" { return false } ret, orderbook := GetOrderBook() if !ret { logger.Infoln("get orderbook failed 1") ret, orderbook = GetOrderBook() //try again if !ret { logger.Infoln("get orderbook failed 2") return false } } logger.Infoln("卖一", orderbook.Asks[len(orderbook.Asks)-1]) logger.Infoln("买一", orderbook.Bids[0]) var flag float64 if orderbook.Bids[0].Price+0.02 > orderbook.Asks[len(orderbook.Asks)-1].Price { flag = 0 } else { flag = 0.01 } for i := 1; i <= ordercount; i++ { warning := "oo, 买入buy In<----限价单" tradePrice := fmt.Sprintf("%f", orderbook.Bids[0].Price+flag) buyID := Buy(tradePrice, splitTradeAmount) if buyID != "0" { warning += "[委托成功]" oo.BuyId = append(oo.BuyId, buyID) } else { warning += "[委托失败]" } logger.Infoln(warning) warning = "oo, 卖出Sell Out---->限价单" tradePrice = fmt.Sprintf("%f", orderbook.Asks[len(orderbook.Asks)-1].Price-flag) sellID := Sell(tradePrice, splitTradeAmount) if sellID != "0" { warning += "[委托成功]" oo.SellId = append(oo.SellId, sellID) } else { warning += "[委托失败]" } logger.Infoln(warning) } //check timeout trade now := time.Now() time.Sleep(10 * time.Second) logger.Infoln("time go ", int64(now.Sub(oo.BuyBegin)/time.Second)) logger.Infoln("BuyId len", len(oo.BuyId), cap(oo.BuyId)) logger.Infoln("SellId len", len(oo.SellId), cap(oo.SellId)) if len(oo.BuyId) != 0 && int64(now.Sub(oo.BuyBegin)/time.Second) > timeout { //todo- for _, BuyId := range oo.BuyId { warning := "<--------------buy order timeout, cancel-------------->" + BuyId if CancelOrder(BuyId) { warning += "[Cancel委托成功]" } else { warning += "[Cancel委托失败]" } logger.Infoln(warning) time.Sleep(1 * time.Second) } oo.BuyId = oo.BuyId[:0] } if len(oo.SellId) != 0 && int64(now.Sub(oo.SellBegin)/time.Second) > timeout { //todo for _, SellId := range oo.SellId { warning := "<--------------sell order timeout, cancel------------->" + SellId if CancelOrder(SellId) { warning += "[Cancel委托成功]" } else { warning += "[Cancel委托失败]" } logger.Infoln(warning) time.Sleep(1 * time.Second) } oo.SellId = oo.SellId[:0] } return true }
func processTimeout() bool { //check timeout trade //last cancel failed, recancel for tm, id := range recancelbuyOrders { warning := fmt.Sprintf("<-----re-cancel %s-------------->", id) if CancelOrder(id) { warning += "[Cancel委托成功]" delete(recancelbuyOrders, tm) } else { warning += "[Cancel委托失败]" } logger.Infoln(warning) time.Sleep(1 * time.Second) time.Sleep(500 * time.Microsecond) } for tm, tradeAmount := range resellOrders { warning := fmt.Sprintf("<-----re-sell %f-------------->", tradeAmount) logger.Infoln(warning) sellID := Sell() if sellID != "0" { warning += "[re-sell委托成功]" delete(resellOrders, tm) sellOrders[time.Now()] = sellID //append or just update "set" } else { warning += "[re-sell委托失败]" } logger.Infoln(warning) time.Sleep(1 * time.Second) time.Sleep(500 * time.Microsecond) } now := time.Now() if len(buyOrders) != 0 { //todo- logger.Infoln("BuyId len", len(buyOrders)) for tm, id := range buyOrders { ret, order := GetOrder(id) if ret == false { continue } if order.Amount == order.Deal_amount { buy_average = (buy_amount*buy_average + order.Deal_amount*order.Price) / (buy_amount + order.Deal_amount) logger.Infof("buy_average=%0.02f\n", buy_average) dealOrders[tm] = order buy_amount += order.Deal_amount delete(buyOrders, tm) } else { if int64(now.Sub(tm)/time.Minute) <= timeout { continue } if order.Deal_amount > 0.0001 { //部分成交的买卖单 buy_average = (buy_amount*buy_average + order.Deal_amount*order.Price) / (buy_amount + order.Deal_amount) logger.Infof("part of buy_average=%0.02f\n", buy_average) dealOrders[tm] = order buy_amount += order.Deal_amount } warning := fmt.Sprintf("<-----buy Delegation timeout, cancel %s[deal:%f]-------------->", id, order.Deal_amount) logger.Infoln(order) if CancelOrder(id) { warning += "[buy Cancel委托成功]" } else { warning += "[buy Cancel委托失败]" recancelbuyOrders[time.Now()] = id } delete(buyOrders, tm) logger.Infoln(warning) time.Sleep(1 * time.Second) time.Sleep(500 * time.Microsecond) } } } if len(sellOrders) != 0 { //todo- logger.Infoln("SellId len", len(sellOrders)) for tm, id := range sellOrders { if int64(now.Sub(tm)/time.Second) <= timeout { continue } ret, order := GetOrder(id) if ret == false { continue } if order.Amount == order.Deal_amount { delete(sellOrders, tm) buy_amount -= order.Deal_amount } else { if int64(now.Sub(tm)/time.Minute) <= timeout { continue } if order.Deal_amount < order.Amount { ret, orderBook := GetOrderBook() if !ret { logger.Infoln("get orderBook failed 1") ret, orderBook = GetOrderBook() //try again if !ret { logger.Infoln("get orderBook failed 2") return false } } warning := "<--------------sell Delegation timeout, cancel-------------->" + id if CancelOrder(id) { warning += "[sell Cancel委托成功]" delete(sellOrders, tm) //update to delete, start a new order for sell in below buy_amount -= order.Deal_amount sell_amount := order.Amount - order.Deal_amount logger.Infoln("卖一", (orderBook.Asks[len(orderBook.Asks)-1])) logger.Infoln("买一", orderBook.Bids[0]) warning := "timeout, resell 卖出Sell Out---->限价单" tradePrice := fmt.Sprintf("%f", orderBook.Asks[len(orderBook.Asks)-1].Price-0.01) tradeAmount := fmt.Sprintf("%f", sell_amount) sellID := sell(tradePrice, tradeAmount) if sellID != "0" { warning += "[resell 委托成功]" sellOrders[time.Now()] = sellID //append or just update "set" } else { warning += "[resell 委托失败]" resellOrders[time.Now()] = tradeAmount } logger.Infoln(warning) } else { warning += "[sell Cancel委托失败]" } logger.Infoln(warning) time.Sleep(1 * time.Second) time.Sleep(500 * time.Microsecond) } } } } return true }
//HLCross strategy func (HLCross *HLCrossStrategy) Tick(records []Record) bool { //read config tradeAmount := Option["tradeAmount"] stoploss, err := strconv.ParseFloat(Option["stoploss"], 64) if err != nil { logger.Errorln("config item stoploss is not float") return false } var Time []string var Price []float64 var Volumn []float64 for _, v := range records { Time = append(Time, v.TimeStr) Price = append(Price, v.Close) Volumn = append(Volumn, v.Volumn) } length := len(Price) if HLCross.PrevClosePrice != records[length-1].Close || HLCross.PrevHighPrice != records[length-2].High || HLCross.PrevLowPrice != records[length-2].Low { HLCross.PrevClosePrice = records[length-1].Close HLCross.PrevHighPrice = records[length-2].High HLCross.PrevLowPrice = records[length-2].Low logger.Infof("nowClose %0.02f prevHigh %0.02f prevLow %0.02f\n", records[length-1].Close, records[length-2].High, records[length-2].Low) } //HLCross cross if records[length-1].Close > records[length-2].High { if Option["enable_trading"] == "1" && HLCross.PrevHLCrossTrade != "buy" { warning := "HLCross up, 买入buy In<----市价" + getTradePrice("", Price[length-1]) + ",委托价" + getTradePrice("buy", Price[length-1]) logger.Infoln(warning) if Buy(getTradePrice("buy", Price[length-1]), tradeAmount) != "0" { HLCross.PrevBuyPirce = Price[length-1] warning += "[委托成功]" HLCross.PrevHLCrossTrade = "buy" } else { warning += "[委托失败]" } go email.TriggerTrender(warning) } } else if records[length-1].Close < records[length-2].Low { if Option["enable_trading"] == "1" && HLCross.PrevHLCrossTrade != "sell" { warning := "HLCross down, 卖出Sell Out---->市价" + getTradePrice("", Price[length-1]) + ",委托价" + getTradePrice("sell", Price[length-1]) logger.Infoln(warning) if Sell(getTradePrice("sell", Price[length-1]), tradeAmount) != "0" { warning += "[委托成功]" HLCross.PrevHLCrossTrade = "sell" HLCross.PrevBuyPirce = 0 } else { warning += "[委托失败]" } go email.TriggerTrender(warning) } } //do sell when price is below stoploss point if Price[length-1] < HLCross.PrevBuyPirce*(1-stoploss*0.01) { if Option["enable_trading"] == "1" && HLCross.PrevHLCrossTrade != "sell" { warning := "stop loss, 卖出Sell Out---->市价" + getTradePrice("", Price[length-1]) + ",委托价" + getTradePrice("sell", Price[length-1]) logger.Infoln(warning) if Sell(getTradePrice("sell", Price[length-1]), tradeAmount) != "0" { warning += "[委托成功]" HLCross.PrevHLCrossTrade = "sell" HLCross.PrevBuyPirce = 0 } else { warning += "[委托失败]" } go email.TriggerTrender(warning) } } return true }
func (w *Huobi) doEMA(Time []string, Price []float64, Volumn []float64) { if len(Price) == 0 { logger.Errorln("no data is prepared!") return } //read config shortEMA, _ := strconv.Atoi(Option["shortEMA"]) longEMA, _ := strconv.Atoi(Option["longEMA"]) stopPoints, err := strconv.ParseFloat(Config["stopPoints"], 64) if err != nil { logger.Debugln("config item stopPoints is not float") return } EMAMinThreshold, err := strconv.ParseFloat(Config["EMAMinThreshold"], 64) if err != nil { logger.Debugln("config item EMAMinThreshold is not float") return } tradeOnlyAfterSwitch, _ := strconv.Atoi(Config["tradeOnlyAfterSwitch"]) TresholdLevel, _ := strconv.Atoi(Config["TresholdLevel"]) _, err = strconv.ParseFloat(Option["tradeAmount"], 64) if err != nil { logger.Debugln("config item tradeAmount is not float") return } tradeAmount := Option["tradeAmount"] f_tradeAmount, err := strconv.ParseFloat(Option["tradeAmount"], 64) if err != nil { logger.Debugln("config item tradeAmount is not float") return } MACDtradeAmount := fmt.Sprintf("%0.02f", f_tradeAmount/2.0) //compute the indictor emaShort := EMA(Price, shortEMA) emaLong := EMA(Price, longEMA) EMAdif := getEMAdif(emaShort, emaLong) length := len(Price) //check indictor using history data, loop through data, get history samples logger.OverrideStart(w.Peroid) logger.Overridef("EMA 收益率分析[%d:[s=%d/l=%d],stopPoints:%0.0f]\n", w.Peroid, shortEMA, longEMA, stopPoints) var profit float64 var times int var lastTrade float64 var entryPrice float64 var totaltimes int if w.Disable_trading != 1 { if Config["env"] == "dev" { logger.Infof("%s\t%-6.2f\t%-6.2f\n", Time[length-1], Price[length-1], Volumn[length-1]) } } //EMA cross for i := 1; i < length; i++ { if EMAdif[i-1] < 0 && EMAdif[i] > 0 { //up cross w.lastAction = "buyIn" totaltimes++ logger.Overrideln(totaltimes) if times == 0 { entryPrice = Price[i] } times++ profit -= Price[i] lastTrade = Price[i] w.lastBuyprice = Price[i] var samplesBegin int if i > longEMA { samplesBegin = i - longEMA } else { samplesBegin = 0 } periodArr := Price[samplesBegin:i] w.lastLowestprice = arrayLowest(periodArr) if EMAdif[i] >= EMAMinThreshold { logger.Overrideln("++ buyIn", i, Time[i], Price[i], fmt.Sprintf("%0.04f", EMAdif[i]), w.lastLowestprice, 2*w.lastBuyprice-w.lastLowestprice) } else { logger.Overrideln(" + buyIn", i, Time[i], Price[i], fmt.Sprintf("%0.04f", EMAdif[i]), w.lastLowestprice, 2*w.lastBuyprice-w.lastLowestprice) } if w.checkException(Price[i-1], Price[i], Volumn[i]) == false { logger.Infoln("detect exception data in huobi.com", Price[i-1], Price[i], Volumn[i]) continue } if i == length-1 && w.latestMACDTrend != 1 { if w.Disable_trading != 1 { logger.Infoln("EMA up cross, 买入buyIn", w.getTradePrice("")) go service.TriggerTrender("EMA up cross, 买入buyIn") } if Option["disable_trading"] != "1" && w.Disable_trading != 1 { w.latestMACDTrend = 1 w.Do_buy(w.getTradePrice("buy"), tradeAmount) } w.backup(Time[i]) } } else if (w.lastAction != "sellOut" || w.lastAction != "stop") && EMAdif[i-1] > 0 && EMAdif[i] < 0 { //down cross w.lastAction = "sellOut" if EMAdif[i] <= -EMAMinThreshold { logger.Overrideln("-- sellOut", i, Time[i], Price[i], fmt.Sprintf("%0.04f", EMAdif[i])) } else { logger.Overrideln(" - sellOut", i, Time[i], Price[i], fmt.Sprintf("%0.04f", EMAdif[i])) } if w.checkException(Price[i-1], Price[i], Volumn[i]) == false { logger.Infoln("detect exception data in huobi.com", Price[i-1], Price[i], Volumn[i]) continue } if i == length-1 && w.latestMACDTrend != -1 { if w.Disable_trading != 1 { logger.Infoln("EMA down cross, 卖出sellOut", w.getTradePrice("")) go service.TriggerTrender("EMA down cross, 卖出sellOut") } if Option["disable_trading"] != "1" && w.Disable_trading != 1 { w.latestMACDTrend = -1 ret := w.Do_sell(w.getTradePrice("sell"), tradeAmount) if ret == false { w.Do_sell(w.getTradePrice("sell"), MACDtradeAmount) } } w.backup(Time[i]) } if times != 0 { times++ profit += Price[i] lastTrade = Price[i] if times != 0 && times%2 == 0 { logger.Overridef("profit=%0.02f, rate=%0.02f%%\n", Price[i]-w.lastBuyprice, 100*(Price[i]-w.lastBuyprice)/w.lastBuyprice) } } } /* else if (w.lastAction != "exit" || w.lastAction != "stop") && Price[i] < emaMiddle[i]-stopPoints { //stop w.lastAction = "stop" logger.Overrideln("-- stop", i, Time[i], Price[i], fmt.Sprintf("%0.04f", emaMiddle[i])) if i == length-1 && w.latestMACDTrend != -1 { logger.Infoln("保守止损位", w.getTradePrice("")) go service.TriggerTrender("保守止损位") ret := w.do_sell(w.getTradePrice("sell"), tradeAmount) if ret == false { w.do_sell(w.getTradePrice("sell"), MACDtradeAmount) } } if times != 0 { times++ profit += Price[i] lastTrade = Price[i] if times != 0 && times%2 == 0 { logger.Overridef("profit=%0.02f, rate=%0.02f%%\n", Price[i]-w.lastBuyprice, 100*(Price[i]-w.lastBuyprice)/w.lastBuyprice) } } }*/ } if times%2 != 0 { profit += lastTrade totaltimes-- } logger.Overridef("totaltimes[%d] profit=%0.02f, entryPrice=%0.02f, rate=%0.02f%%\n", totaltimes, profit, entryPrice, 100*profit/entryPrice) if false { //current trend //trade according trend indictor if w.latestSolidTrend == 0 { w.findLatestSolidTrend(emaShort, emaLong, EMAMinThreshold, TresholdLevel, length) } w.trade(emaShort, emaLong, EMAMinThreshold, TresholdLevel, length, tradeOnlyAfterSwitch, tradeAmount) } }
//EMA strategy func (emaStrategy *EMAStrategy) Tick(records []Record) bool { //read config shortEMA, _ := strconv.Atoi(Option["shortEMA"]) longEMA, _ := strconv.Atoi(Option["longEMA"]) var Price []float64 for _, v := range records { Price = append(Price, v.Close) } //compute the indictor emaShort := EMA(Price, shortEMA) emaLong := EMA(Price, longEMA) EMAdif := getMACDdif(emaShort, emaLong) if emaStrategy.PrevEMACross == "unknown" { if is_uptrend(EMAdif[length-3]) { emaStrategy.PrevEMACross = "up" } else if is_downtrend(EMAdif[length-3]) { emaStrategy.PrevEMACross = "down" } else { emaStrategy.PrevEMACross = "unknown" } logger.Infoln("prev cross is", emaStrategy.PrevEMACross) if is_uptrend(EMAdif[length-3]) { logger.Infoln("上一个趋势是上涨,等待卖出点触发") } else if is_downtrend(EMAdif[length-3]) { logger.Infoln("上一个趋势是下跌,等待买入点触发") } else { logger.Infoln("上一个趋势是unknown。。。") } } //go TriggerPrice(Price[length-1]) if EMAdif[length-1] != emaStrategy.PrevEMAdif { emaStrategy.PrevEMAdif = EMAdif[length-1] logger.Infof("EMA [%0.02f,%0.02f,%0.02f] Diff:%0.04f\t%0.04f\n", lastPrice, emaShort[length-1], emaLong[length-1], EMAdif[length-2], EMAdif[length-1]) } //reset LessBuyThreshold LessSellThreshold flag when (^ or V) happen if emaStrategy.LessBuyThreshold && is_downtrend(EMAdif[length-1]) { emaStrategy.LessBuyThreshold = false emaStrategy.PrevEMACross = "down" //reset logger.Infoln("down->up(EMA diff < buy threshold)->down ^") } if emaStrategy.LessSellThreshold && is_uptrend(EMAdif[length-1]) { emaStrategy.LessSellThreshold = false emaStrategy.PrevEMACross = "up" //reset logger.Infoln("up->down(EMA diff > sell threshold)->up V") } //EMA cross if (emaStrategy.is_upcross(EMAdif[length-2], EMAdif[length-1]) || emaStrategy.LessBuyThreshold) || (emaStrategy.is_downcross(EMAdif[length-2], EMAdif[length-1]) || emaStrategy.LessSellThreshold) { //up cross //do buy when cross up if emaStrategy.is_upcross(EMAdif[length-2], EMAdif[length-1]) || emaStrategy.LessBuyThreshold { if Option["enable_trading"] == "1" && PrevTrade != "buy" { emaStrategy.PrevEMACross = "up" if emaStrategy.checkThreshold("buy", EMAdif[length-1]) { Buy() } } } //do sell when cross down if emaStrategy.is_downcross(EMAdif[length-2], EMAdif[length-1]) || emaStrategy.LessSellThreshold { emaStrategy.PrevEMACross = "down" if Option["enable_trading"] == "1" && PrevTrade != "sell" { if emaStrategy.checkThreshold("sell", EMAdif[length-1]) { Sell() } } } //backup the kline data for analyze if Config["env"] == "dev" { backup(records[length-1].TimeStr) } } //do sell when price is below stoploss point processStoploss(lastPrice) processTimeout() return true }
//xxx strategy func (kdjStrategy *KDJStrategy) Tick(records []Record) bool { //实现自己的策略 tradeAmount := Option["tradeAmount"] var Time []string var Price []float64 var Volumn []float64 for _, v := range records { Time = append(Time, v.TimeStr) Price = append(Price, v.Close) Volumn = append(Volumn, v.Volumn) //Price = append(Price, (v.Close+v.Open+v.High+v.Low)/4.0) //Price = append(Price, v.Low) } length := len(records) if kdjStrategy.PrevTime == records[length-1].TimeStr && kdjStrategy.PrevPrice == records[length-1].Close { return false } //K线为白,D线为黄,J线为红,K in middle k, d, j := getKDJ(records) if kdjStrategy.PrevTime != records[length-1].TimeStr || kdjStrategy.PrevPrice != records[length-1].Close { kdjStrategy.PrevTime = records[length-1].TimeStr kdjStrategy.PrevPrice = records[length-1].Close logger.Infoln(records[length-1].TimeStr, records[length-1].Close) logger.Infof("d(黄线)%0.0f\tk(白线)%0.0f\tj(红线)%0.0f\n", d[length-2], k[length-2], j[length-2]) logger.Infof("d(黄线)%0.0f\tk(白线)%0.0f\tj(红线)%0.0f\n", d[length-1], k[length-1], j[length-1]) } if ((j[length-2] < k[length-2] && k[length-2] < d[length-2]) || kdjStrategy.PrevKDJTrade == "sell") && (j[length-1] > k[length-1] && k[length-1] > d[length-1]) { logger.Infoln("KDJ up cross") if (kdjStrategy.PrevKDJTrade == "init" && d[length-2] <= 30) || kdjStrategy.PrevKDJTrade == "sell" { //do buy warning := "KDJ up cross, 买入buy In<----市价" + getTradePrice("", Price[length-1]) + ",委托价" + getTradePrice("buy", Price[length-1]) logger.Infoln(warning) if Buy(getTradePrice("buy", Price[length-1]), tradeAmount) != "0" { warning += "[委托成功]" } else { warning += "[委托失败]" } kdjStrategy.PrevKDJTrade = "buy" go email.TriggerTrender(warning) } } if ((j[length-2] > k[length-2] && k[length-2] > d[length-2]) || kdjStrategy.PrevKDJTrade == "buy") && (j[length-1] < k[length-1] && k[length-1] < d[length-1]) { logger.Infoln("KDJ down cross") if (kdjStrategy.PrevKDJTrade == "init" && d[length-2] >= 70) || kdjStrategy.PrevKDJTrade == "buy" { //do sell warning := "KDJ down cross, 卖出Sell Out---->市价" + getTradePrice("", Price[length-1]) + ",委托价" + getTradePrice("sell", Price[length-1]) logger.Infoln(warning) if Sell(getTradePrice("sell", Price[length-1]), tradeAmount) != "0" { warning += "[委托成功]" } else { warning += "[委托失败]" } kdjStrategy.PrevKDJTrade = "sell" go email.TriggerTrender(warning) } } return true }