func Sell() string { if PrevTrade == "sell" { return "0" } // compute the price price, _, warning := getSellPrice() // compute the amount Available_coin := GetAvailable_coin() if Available_coin < 0.01 { warning = "没有足够的币" logger.Infoln(warning) PrevTrade = "sell" PrevBuyPirce = 0 return "0" } amount := Option["tradeAmount"] nAmount, err := strconv.ParseFloat(amount, 64) if err != nil { logger.Infoln("amount is not float") return "0" } if nAmount > Available_coin { nAmount = Available_coin amount = fmt.Sprintf("%02f", nAmount) } sellID := sell(price, amount) if sellID == "-1" { warning += " [模拟]" } else if sellID == "0" { warning += "[委托失败]" } else { warning += "[委托成功]" + sellID } logger.Infoln(warning) var coin string if Option["symbol"] == "btc_cny" { coin = "比特币" } else { coin = "莱特币" } if sellID != "0" { if !GetBacktest() { logger.Tradef("在%s,根据策略%s周期%s,以价格%s卖出%s个%s\n", Option["tradecenter"], Option["strategy"], Option["tick_interval"], price, amount, coin) go email.TriggerTrender(warning) } else { t := time.Unix(GetBtTime(), 0) logger.Backtestf("%s 在simulate,根据策略%s周期%s,以价格%s卖出%s个%s\n", t.Format("2006-01-02 15:04:05"), Option["strategy"], Option["tick_interval"], price, amount, coin) } } return sellID }
// KDJ-EX strategy func (kdjex *KDJexStrategy) Tick(records []Record) bool { const btcslap = 0.2 const ltcslap = 0.01 const timeout = 300 // 秒 const ordercount = 5 tradeAmount := Option["tradeAmount"] numTradeAmount, err := strconv.ParseFloat(Option["tradeAmount"], 64) if err != nil { logger.Errorln("config item tradeAmount is not float") return false } var slappage float64 symbol := Option["symbol"] if symbol == "btc_cny" { slappage = btcslap } else { slappage = ltcslap } var coin string if Option["symbol"] == "btc_cny" { coin = "比特币" } else { coin = "莱特币" } nSplitTradeAmount := numTradeAmount / float64(ordercount) splitTradeAmount := fmt.Sprintf("%f", nSplitTradeAmount) 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(records) if kdjex.PrevTime == records[length-1].TimeStr && kdjex.PrevPrice == records[length-1].Close { return false } // K线为白,D线为黄,J线为红,K in middle k, d, j := getKDJ(records) if kdjex.PrevTime != records[length-1].TimeStr || kdjex.PrevPrice != records[length-1].Close { kdjex.PrevTime = records[length-1].TimeStr kdjex.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-1] > k[length-1] { logger.Infoln("KDJ up trend") } else { logger.Infoln("KDJ down trend") } } if (j[length-2] < k[length-2] && k[length-2] < d[length-2]) && (j[length-1] > k[length-1] && k[length-1] > d[length-1]) { logger.Infoln("----------------->KDJ up cross", kdjex.PrevKDJTrade, d[length-2]) if kdjex.PrevKDJTrade != "buy" && j[length-2] <= 20 { // do buy 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]) logger.Infoln("X 两根K线最低价", records[length-2].Low, records[length-1].Low) logger.Infoln("X 两根K线最高价", records[length-2].High, records[length-1].High) avgLow := (records[length-2].Close + records[length-1].Low) / 2.0 logger.Infoln("X 两根K线的最低平均价", avgLow) warning := "KDJ up cross, 买入buy In<----限价单" for i := 1; i <= ordercount; i++ { warning := "KDJ up cross, 买入buy In<----限价单" tradePrice := fmt.Sprintf("%f", avgLow+slappage*float64(i)) buyID := buy(tradePrice, splitTradeAmount) if buyID != "0" { warning += "[委托成功]" kdjex.BuyId = append(kdjex.BuyId, buyID) if !GetBacktest() { logger.Tradef("在%s,根据策略%s周期%s,以价格%s买入%s个%s\n", Option["tradecenter"], Option["strategy"], Option["tick_interval"], tradePrice, splitTradeAmount, coin) } else { t := time.Unix(GetBtTime(), 0) logger.Backtestf("%s 在simulate,根据策略%s周期%s,以价格%s买入%s个%s\n", t.Format("2006-01-02 15:04:05"), Option["strategy"], Option["tick_interval"], tradePrice, splitTradeAmount, coin) } } else { warning += "[委托失败]" } logger.Infoln(warning) } kdjex.BuyBegin = time.Now() kdjex.PrevKDJTrade = "buy" kdjex.PrevBuyPirce = avgLow logger.Infoln("------------>>>stoploss price", kdjex.PrevBuyPirce*(1-stoploss*0.01)) _, ret = GetAccount() if !ret { logger.Infoln("GetAccount failed") } SendEmail(warning) } } if (j[length-2] > k[length-2] && k[length-2] > d[length-2]) && (j[length-1] < k[length-1] && k[length-1] < d[length-1]) { logger.Infoln("<----------------------KDJ down cross", kdjex.PrevKDJTrade, d[length-2]) if kdjex.PrevKDJTrade != "sell" && j[length-2] >= 80 { // do sell 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]) logger.Infoln("X 两根K线最低价", records[length-2].Low, records[length-1].Low) logger.Infoln("X 两根K线最高价", records[length-2].High, records[length-1].High) avgHigh := (records[length-2].Close + records[length-1].High) / 2.0 logger.Infoln("X 两根K线的最高平均价", avgHigh) warning := "KDJ down cross, 卖出Sell Out---->限价单" for i := 1; i <= ordercount; i++ { warning := "KDJ down cross, 卖出Sell Out---->限价单" tradePrice := fmt.Sprintf("%f", avgHigh-slappage*float64(i)) sellID := sell(tradePrice, splitTradeAmount) if sellID != "0" { warning += "[委托成功]" kdjex.SellId = append(kdjex.SellId, sellID) if !GetBacktest() { logger.Tradef("在%s,根据策略%s周期%s,以价格%s卖出%s个%s\n", Option["tradecenter"], Option["strategy"], Option["tick_interval"], tradePrice, splitTradeAmount, coin) } else { t := time.Unix(GetBtTime(), 0) logger.Backtestf("%s 在simulate,根据策略%s周期%s,以价格%s卖出%s个%s\n", t.Format("2006-01-02 15:04:05"), Option["strategy"], Option["tick_interval"], tradePrice, splitTradeAmount, coin) } } else { warning += "[委托失败]" } logger.Infoln(warning) } kdjex.SellBegin = time.Now() kdjex.PrevKDJTrade = "sell" _, ret = GetAccount() if !ret { logger.Infoln("GetAccount failed") } SendEmail(warning) } } // do sell when price is below stoploss point if Price[length-1] < kdjex.PrevBuyPirce*(1-stoploss*0.01) { if Option["disable_trading"] != "1" && kdjex.PrevKDJTrade != "sell" { kdjex.PrevKDJTrade = "sell" kdjex.PrevBuyPirce = 0 warning := "!<------------------stop loss, 卖出Sell Out---->市价" + getTradePrice("", Price[length-1]) + ",委托价" + getTradePrice("sell", Price[length-1]) logger.Infoln(warning) tradePrice := getTradePrice("sell", Price[length-1]) if sell(tradePrice, tradeAmount) != "0" { warning += "[委托成功]" if !GetBacktest() { logger.Tradef("在%s,根据策略%s周期%s,以价格%s卖出%s个%s\n", Option["tradecenter"], Option["strategy"], Option["tick_interval"], tradePrice, tradeAmount, coin) } else { t := time.Unix(GetBtTime(), 0) logger.Backtestf("%s 在simulate,根据策略%s周期%s,以价格%s卖出%s个%s\n", t.Format("2006-01-02 15:04:05"), Option["strategy"], Option["tick_interval"], tradePrice, tradeAmount, coin) } } else { warning += "[委托失败]" for i := 1; i <= ordercount; i++ { warning := "stop loss, 卖出Sell Out---->限价单" tradePrice := getTradePrice("sell", Price[length-1]) sellID := sell(tradePrice, splitTradeAmount) if sellID != "0" { warning += "[委托成功]" kdjex.SellId = append(kdjex.SellId, sellID) if !GetBacktest() { logger.Tradef("在%s,根据策略%s周期%s,以价格%s卖出%s个%s\n", Option["tradecenter"], Option["strategy"], Option["tick_interval"], tradePrice, splitTradeAmount, coin) } else { t := time.Unix(GetBtTime(), 0) logger.Backtestf("%s 在simulate,根据策略%s周期%s,以价格%s卖出%s个%s\n", t.Format("2006-01-02 15:04:05"), Option["strategy"], Option["tick_interval"], tradePrice, splitTradeAmount, coin) } } else { warning += "[委托失败]" } logger.Infoln(warning) } } kdjex.SellBegin = time.Now() kdjex.PrevKDJTrade = "sell" _, ret := GetAccount() if !ret { logger.Infoln("GetAccount failed") } SendEmail(warning) } } // check timeout trade now := time.Now() logger.Infoln("time go ", int64(now.Sub(kdjex.BuyBegin)/time.Second)) logger.Infoln("BuyId len", len(kdjex.BuyId), cap(kdjex.BuyId)) logger.Infoln("SellId len", len(kdjex.SellId), cap(kdjex.SellId)) if len(kdjex.BuyId) != 0 && int64(now.Sub(kdjex.BuyBegin)/time.Second) > timeout { // todo for _, BuyId := range kdjex.BuyId { warning := "<--------------buy order timeout, cancel-------------->" + BuyId if CancelOrder(BuyId) { warning += "[Cancel委托成功]" } else { warning += "[Cancel委托失败]" } logger.Infoln(warning) time.Sleep(1 * time.Second) time.Sleep(500 * time.Microsecond) } kdjex.BuyId = kdjex.BuyId[:0] } if len(kdjex.SellId) != 0 && int64(now.Sub(kdjex.SellBegin)/time.Second) > timeout { // todo for _, SellId := range kdjex.SellId { warning := "<--------------sell order timeout, cancel------------->" + SellId if CancelOrder(SellId) { warning += "[Cancel委托成功]" } else { warning += "[Cancel委托失败]" } logger.Infoln(warning) time.Sleep(1 * time.Second) time.Sleep(500 * time.Microsecond) } kdjex.SellId = kdjex.SellId[:0] } return true }
func Buy() string { if PrevTrade == "buy" { return "0" } // init isStoploss = false // compute the price price, nPrice, warning := getBuyPrice() // compute the amount amount := Option["tradeAmount"] nAmount, err := strconv.ParseFloat(amount, 64) if err != nil { logger.Infoln("amount is not float") return "0" } Available_cny := GetAvailable_cny() if Available_cny < nPrice*nAmount { var nMinTradeAmount float64 nAmount = Available_cny / nPrice symbol := Option["symbol"] if symbol == "btc_cny" { nMinTradeAmount = 0.1 } else { nMinTradeAmount = 0.01 } if nAmount < nMinTradeAmount { warning += "没有足够的法币余额" logger.Infoln(warning) PrevTrade = "buy" PrevBuyPirce = nPrice return "0" } amount = fmt.Sprintf("%02f", nAmount) } warning += "---->数量" + amount buyID := buy(price, amount) if buyID == "-1" { warning += " [模拟]" } else if buyID == "0" { warning += "[委托失败]" } else { warning += "[委托成功]" + buyID } logger.Infoln(warning) var coin string if Option["symbol"] == "btc_cny" { coin = "比特币" } else { coin = "莱特币" } if buyID != "0" { if !GetBacktest() { logger.Tradef("在%s,根据策略%s周期%s,以价格%s买入%s个%s\n", Option["tradecenter"], Option["strategy"], Option["tick_interval"], price, amount, coin) go email.TriggerTrender(warning) } else { t := time.Unix(GetBtTime(), 0) logger.Backtestf("%s 在simulate,根据策略%s周期%s,以价格%s买入%s个%s\n", t.Format("2006-01-02 15:04:05"), Option["strategy"], Option["tick_interval"], price, amount, coin) } } return buyID }