Example #1
0
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
}
Example #2
0
func (strategy *KDJStrategy) kdjSell(price float64) {
	price = price - 0.5
	strategy.PrevPrice = price
	priceStr := fmt.Sprintf("%f", price)
	amount := Option["tradeAmount"]
	sell(priceStr, amount)
	strategy.PrevTrade = "sell"
	t := time.Unix(GetBtTime(), 0)
	logger.Backtestf("%s 在simulate,根据策略%s周期%s,以价格%f卖出%s个%s\n", t.Format("2006-01-02 15:04:05"), Option["strategy"], Option["tick_interval"], price, amount, "比特币")
}
Example #3
0
func (threelineStrategy *ThreelineStrategy) Sell(price float64) {
	price = price - StringToFloat(Option["slippage"])
	threelineStrategy.BuyPrice = 0
	priceStr := fmt.Sprintf("%f", price)
	amount := Option["tradeAmount"]
	sell(priceStr, amount)
	threelineStrategy.PrevTrade = "sell"
	t := time.Unix(GetBtTime(), 0)
	logger.Backtestf("%s 在simulate,根据策略%s周期%s,以价格%f卖出%s个%s\n",
		t.Format("2006-01-02 15:04:05"), Option["strategy"], Option["tick_interval"],
		price, amount, coinName())
}
Example #4
0
func backtesting() {
	fmt.Println("back testing begin...")

	SetBacktest(true)
	SimAccount = make(map[string]string)
	SimAccount["CNY"] = IntegerToString(BackTestCNY)
	SimAccount["BTC"] = "0"
	SimAccount["LTC"] = "0"
	SaveSimulate()

	btEnd := time.Now()
	btEnd = time.Date(btEnd.Year(), btEnd.Month(), btEnd.Day(), btEnd.Hour(), btEnd.Minute(), 0, 0, time.Local)
	//btEnd = btEnd.AddDate(0, 0, -1)
	//btStart := btEnd.AddDate(0, -3, 0)

	btEnd = btEnd.Add(0 - time.Second*3600*2)
	btStart := btEnd.Add(0 - time.Second*3600*24*30)

	day := time.Second * 3600 * 24
	dayshift := 0
	btEnd = btEnd.Add(0 - day*time.Duration(dayshift))
	btStart = btStart.Add(0 - day*time.Duration(dayshift))

	var symbolId string
	if Option["symbol"] == "btc_cny" {
		symbolId = "btccny"
	} else {
		symbolId = "ltccny"
	}

	fmt.Println("回测开始时间", btStart.Format("2006-01-02 15:04:05"))
	fmt.Println("回测结束时间", btEnd.Format("2006-01-02 15:04:05"))

	period := StringToInteger(Option["tick_interval"])

	var records []Record
	var err error
	datacenter := Option["datacenter"]
	if datacenter == "huobi" {
		records, err = GetKLine(btStart, btEnd, period, symbolId)
	} else {
		records, err = OkcoinKLine(period, symbolId)
	}
	if err != nil {
		fmt.Println(err)
		return
	} else {
		fmt.Println(len(records))
	}

	if Option["tick_interval"] != "1" {
		// check exception data
		for i := 0; i < len(records)-1; i++ {
			if strategy.CheckException(records[i], records[i+1]) == false {
				logger.Errorln("detect exception data ",
					records[i].Close, records[i+1].Close, records[i+1].Volumn)
				return
			}
		}
	}

	filepath := btStart.Format("2006-01-02") + "_" + btEnd.Format("2006-01-02")
	filepath = "\\test\\" + filepath + "_" + IntegerToString(period) + "_" + symbolId
	filepath = filepath + "_" + Option["strategy"] + ".txt"
	logger.SetBacktestFile(filepath)
	DeleteFile(ROOT + filepath)

	for i := ShiftNumber; i < len(records); i++ {
		var rec []Record
		if i < MaxKLineLength {
			rec = records[0:i]
		} else {
			rec = records[i-MaxKLineLength : i]
		}
		SetBtTime(rec[len(rec)-1].Time)
		SetBtPrice(records[i].Close)
		strategy.Tick(simulate.NewSimulate(), rec)
	}

	var coin float64
	var total float64
	if symbolId == "btccny" {
		coin = StringToFloat(SimAccount["BTC"])
		total = coin*records[len(records)-1].Close + StringToFloat(SimAccount["CNY"])
	} else {
		coin = StringToFloat(SimAccount["LTC"])
		total = coin*records[len(records)-1].Close + StringToFloat(SimAccount["CNY"])
	}
	logger.Backtestf("资金总计:%f    盈亏比:%f \n", total, (total-BackTestCNY)/BackTestCNY*100)

	//peroids := []int{1, 5, 15, 30, 60, 100}
	//for _, peroid := range peroids {
	//	if huobi.AnalyzeKLinePeroid("btc_cny", peroid) == true {
	//	} else {
	//		logger.Errorln("TradeKLine failed.")
	//	}
	//}
	//fmt.Println("生成 1/5/15/30/60分钟及1天 周期的后向测试报告于log/reportxxx.log文件中,请查看")

	fmt.Println("back testing end ...")
}
Example #5
0
// 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
}
Example #6
0
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
}