Esempio n. 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
}
Esempio n. 2
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)
	go email.TriggerTrender(warning)

	return buyID
}
Esempio n. 3
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)
	go email.TriggerTrender(warning)

	return sellID
}
Esempio n. 4
0
func SecretHandler(rw http.ResponseWriter, req *http.Request) {
	if !Basic(rw, req) {
		return
	}
	vars := mux.Vars(req)
	msgtype := vars["msgtype"]
	if req.Method != "POST" && msgtype == "" {
		// 获取用户信息
		err := config.LoadSecretOption()
		if err != nil {
			fmt.Fprint(rw, `{"errno": 1, "error":"`, "读取秘钥配置数据失败", `"}`)
			return
		}
		// 设置模板数据
		filter.SetData(req, map[string]interface{}{"config": config.SecretOption})
		req.Form.Set(filter.CONTENT_TPL_KEY, "/template/trade/secret.html")
		return
	} else {
		config.SecretOption["username"] = req.FormValue("username")
		config.SecretOption["password"] = req.FormValue("password")

		config.SecretOption["huobi_access_key"] = req.FormValue("huobi_access_key")
		config.SecretOption["huobi_secret_key"] = req.FormValue("huobi_secret_key")

		config.SecretOption["ok_partner"] = req.FormValue("ok_partner")
		config.SecretOption["ok_secret_key"] = req.FormValue("ok_secret_key")

		config.SecretOption["smtp_username"] = req.FormValue("smtp_username")
		config.SecretOption["smtp_password"] = req.FormValue("smtp_password")
		config.SecretOption["smtp_host"] = req.FormValue("smtp_host")
		config.SecretOption["smtp_addr"] = req.FormValue("smtp_addr")

		// 更新个人信息
		err := config.SaveSecretOption()
		if err != nil {
			fmt.Fprint(rw, `{"errno": 1, "error":"`, "写入秘钥配置数据失败", `"}`)
			return
		}

		fmt.Fprint(rw, `{"errno": 0, "msg":"更新秘钥配置成功!"}`)

		go email.TriggerTrender("btcrobot测试邮件,您能收到这封邮件说明您的SMTP配置成功,来自星星的机器人")
	}
}
Esempio n. 5
0
func webui() {
	m := martini.Classic()
	m.Get("/secret", func() string {
		// show something
		err := LoadSecretOption()
		if err != nil {
			logger.Errorln(err)
			return `{"errno": 1, "msg":", "读取秘钥配置数据失败"}`
		}
		Option_json, err := json.Marshal(SecretOption)
		if err != nil {
			logger.Errorln(err)
			return `{"errno": 1, "msg":", "解析秘钥配置数据失败"}`
		}

		return string(Option_json)
	})

	m.Post("/secret", func(res http.ResponseWriter, req *http.Request) { // res and req are injected by Martini
		SecretOption["username"] = req.FormValue("username")
		SecretOption["password"] = req.FormValue("password")

		SecretOption["bitvc_email"] = req.FormValue("bitvc_email")
		SecretOption["bitvc_password"] = req.FormValue("bitvc_password")

		SecretOption["huobi_access_key"] = req.FormValue("huobi_access_key")
		SecretOption["huobi_secret_key"] = req.FormValue("huobi_secret_key")

		SecretOption["smtp_username"] = req.FormValue("smtp_username")
		SecretOption["smtp_password"] = req.FormValue("smtp_password")
		SecretOption["smtp_host"] = req.FormValue("smtp_host")
		SecretOption["smtp_addr"] = req.FormValue("smtp_addr")

		SecretOption["OKCoinAPIkey"] = req.FormValue("OKCoinAPIkey")

		SecretOption["ok_partner"] = req.FormValue("ok_partner")
		SecretOption["ok_secret_key"] = req.FormValue("ok_secret_key")

		SecretOption["ok_partner1"] = req.FormValue("ok_partner1")
		SecretOption["ok_secret_key1"] = req.FormValue("ok_secret_key1")

		SecretOption["ok_partner2"] = req.FormValue("ok_partner2")
		SecretOption["ok_secret_key2"] = req.FormValue("ok_secret_key2")

		SecretOption["ok_partner3"] = req.FormValue("ok_partner3")
		SecretOption["ok_secret_key3"] = req.FormValue("ok_secret_key3")

		SecretOption["ok_partner4"] = req.FormValue("ok_partner4")
		SecretOption["ok_secret_key4"] = req.FormValue("ok_secret_key4")

		SecretOption["ok_partner5"] = req.FormValue("ok_partner5")
		SecretOption["ok_secret_key5"] = req.FormValue("ok_secret_key5")

		SecretOption["ok_partner6"] = req.FormValue("ok_partner6")
		SecretOption["ok_secret_key6"] = req.FormValue("ok_secret_key6")

		SecretOption["ok_partner7"] = req.FormValue("ok_partner7")
		SecretOption["ok_secret_key7"] = req.FormValue("ok_secret_key7")

		SecretOption["ok_partner8"] = req.FormValue("ok_partner8")
		SecretOption["ok_secret_key8"] = req.FormValue("ok_secret_key8")

		SecretOption["ok_partner9"] = req.FormValue("ok_partner9")
		SecretOption["ok_secret_key9"] = req.FormValue("ok_secret_key9")

		SecretOption["ok_partner10"] = req.FormValue("ok_partner10")
		SecretOption["ok_secret_key10"] = req.FormValue("ok_secret_key10")

		// 更新个人信息
		err := SaveSecretOption()
		if err != nil {
			fmt.Fprint(res, "写入秘钥配置数据失败")
			return
		}

		fmt.Fprint(res, "更新秘钥配置成功!")

		go email.TriggerTrender("btcrobot测试邮件,您能收到这封邮件说明您的SMTP配置成功,来自星星的机器人")

		return
	})

	m.Get("/engine", func() string {
		// show something
		err := LoadOption()
		if err != nil {
			logger.Errorln(err)
			return `{"errno": 1, "msg":", "读取引擎配置数据失败"}`
		}
		Option_json, err := json.Marshal(Option)
		if err != nil {
			logger.Errorln(err)
			return `{"errno": 1, "msg":", "解析引擎配置数据失败"}`
		}

		return string(Option_json)
	})

	m.Post("/engine", func(res http.ResponseWriter, req *http.Request) {
		if req.FormValue("enable_trading") == "on" {
			Option["enable_trading"] = "1"
		} else {
			Option["enable_trading"] = "0"
		}

		if req.FormValue("discipleMode") == "on" {
			Option["discipleMode"] = "1"
		} else {
			Option["discipleMode"] = "0"
		}

		Option["discipleValue"] = req.FormValue("discipleValue")

		// open传递过来的是“on”或没传递
		if req.FormValue("enable_email") == "on" {
			Option["enable_email"] = "1"
		} else {
			Option["enable_email"] = "0"
		}

		Option["to_email"] = req.FormValue("to_email")

		Option["tick_interval"] = req.FormValue("tick_interval")
		Option["datacenter"] = req.FormValue("datacenter")
		Option["tradecenter"] = req.FormValue("tradecenter")
		Option["symbol"] = req.FormValue("symbol")
		Option["strategy"] = req.FormValue("strategy")
		Option["shortEMA"] = req.FormValue("shortEMA")
		Option["longEMA"] = req.FormValue("longEMA")
		Option["signalPeriod"] = req.FormValue("signalPeriod")

		Option["tradeAmount"] = req.FormValue("tradeAmount")
		Option["slippage"] = req.FormValue("slippage")

		Option["totalHour"] = req.FormValue("totalHour")
		Option["buyThreshold"] = req.FormValue("buyThreshold")
		Option["sellThreshold"] = req.FormValue("sellThreshold")
		Option["MACDbuyThreshold"] = req.FormValue("MACDbuyThreshold")
		Option["MACDsellThreshold"] = req.FormValue("MACDsellThreshold")

		Option["basePrice"] = req.FormValue("basePrice")
		Option["fluctuation"] = req.FormValue("fluctuation")

		Option["stoploss"] = req.FormValue("stoploss")

		// 更新个人信息
		err := SaveOption()
		if err != nil {
			fmt.Fprint(res, "写入引擎配置数据失败")
			return
		}

		fmt.Fprint(res, "更新引擎配置成功!")
	})

	m.Get("/trade", func() string {
		// show something
		LoadTrade()

		err := LoadTrade()
		if err != nil {
			logger.Errorln(err)
			return `{"errno": 1, "msg":", "读取Trade配置数据失败"}`
		}

		Option_json, err := json.Marshal(TradeOption)
		if err != nil {
			logger.Errorln(err)
			return `{"errno": 1, "msg":", "解析引擎配置数据失败"}`
		}

		return string(Option_json)
	})

	m.Post("/trade", func(res http.ResponseWriter, req *http.Request) {
		msgtype := req.FormValue("msgtype")
		var nbuyprice, nbuytotalamount, nbuyinterval, nmaxbuyamountratio float64
		var nbuytimes int
		var nsellprice, nselltotalamount, nsellinterval, nmaxsellamountratio float64
		var nselltimes int

		var err error
		if msgtype == "dobuy" {
			TradeOption["buyprice"] = req.FormValue("buyprice")
			TradeOption["buytotalamount"] = req.FormValue("buytotalamount")
			TradeOption["buyinterval"] = req.FormValue("buyinterval")
			TradeOption["buytimes"] = req.FormValue("buytimes")
			TradeOption["maxbuyamountratio"] = req.FormValue("maxbuyamountratio")
			nbuyprice, err = strconv.ParseFloat(Option["buyprice"], 64)
			if err != nil {
				logger.Errorln("config item buyprice is not float")
				return
			}
			nbuytotalamount, err = strconv.ParseFloat(Option["buytotalamount"], 64)
			if err != nil {
				logger.Errorln("config item numbuytotalamount is not float")
				return
			}
			nbuyinterval, err = strconv.ParseFloat(Option["buyinterval"], 64)
			if err != nil {
				logger.Errorln("config item buyinterval is not float")
				return
			}
			nbuytimes, err = strconv.Atoi(Option["buytimes"])
			if err != nil {
				logger.Errorln("config item numbuytimes is not float")
				return
			}

			nmaxbuyamountratio, err = strconv.ParseFloat(Option["maxbuyamountratio"], 64)
			if err != nil {
				logger.Errorln("config item numbuytotalamount is not float")
				return
			}
		} else if msgtype == "dosell" {
			TradeOption["sellprice"] = req.FormValue("sellprice")
			TradeOption["selltotalamount"] = req.FormValue("selltotalamount")
			TradeOption["sellinterval"] = req.FormValue("sellinterval")
			TradeOption["selltimes"] = req.FormValue("selltimes")
			TradeOption["maxsellamountratio"] = req.FormValue("maxsellamountratio")

			nsellprice, err = strconv.ParseFloat(Option["sellprice"], 64)
			if err != nil {
				logger.Errorln("config item sellprice is not float")
				return
			}
			nselltotalamount, err = strconv.ParseFloat(Option["selltotalamount"], 64)
			if err != nil {
				logger.Errorln("config item selltotalamount is not float")
				return
			}
			nsellinterval, err = strconv.ParseFloat(Option["v"], 64)
			if err != nil {
				logger.Errorln("config item sellinterval is not float")
				return
			}
			nselltimes, err = strconv.Atoi(Option["selltimes"])
			if err != nil {
				logger.Errorln("config item selltimes is not float")
				return
			}

			nmaxsellamountratio, err = strconv.ParseFloat(Option["maxsellamountratio"], 64)
			if err != nil {
				logger.Errorln("config item maxsellamountratio is not float")
				return
			}

		} else {
			fmt.Fprint(res, "无效的POST请求")
		}

		// 更新个人信息
		err = SaveTrade()
		if err != nil {
			fmt.Fprint(res, "写入Trade配置数据失败")
		}

		var tradeAPI TradeAPI
		if Option["tradecenter"] == "huobi" {
			tradeAPI = huobi.NewHuobi()
		} else if Option["tradecenter"] == "okcoin" {
			tradeAPI = okcoin.NewOkcoin()
		} else {
			fmt.Fprint(res, "没有选择交易所名称")
		}

		var ret string

		var arrbuyTradePrice []float64
		splitnbuyinterval := nbuyinterval / float64(nbuytimes)
		splitbuyTradeAmount := nbuytotalamount / float64(nbuytimes)
		if splitbuyTradeAmount/nbuytotalamount > nmaxbuyamountratio {
			return
		}

		if msgtype == "dobuy" {
			for i := 0; i < nbuytimes; i++ {
				warning := "oo, 买入buy In<----限价单"

				if i < nbuytimes/2 {
					arrbuyTradePrice[i] = nbuyprice - float64(i)*splitnbuyinterval
				} else {
					arrbuyTradePrice[i] = nbuyprice + float64((i-nbuytimes/2))*splitnbuyinterval
				}

				tradePrice := fmt.Sprintf("%f", arrbuyTradePrice[i])
				strsplitTradeAmount := fmt.Sprintf("%f", splitbuyTradeAmount)

				ret = tradeAPI.Buy(tradePrice, strsplitTradeAmount)

				if ret != "0" {
					fmt.Fprint(res, "交易委托成功")
				} else {
					fmt.Fprint(res, "交易委托失败")
				}
				logger.Infoln(warning)
			}
		}

		var arrsellTradePrice []float64
		splitnsellinterval := nsellinterval / float64(nselltimes)
		splitsellTradeAmount := nselltotalamount / float64(nselltimes)
		if splitsellTradeAmount/nselltotalamount > nmaxsellamountratio {
			return
		}
		if msgtype == "dosell" {
			for i := 0; i < nselltimes; i++ {
				warning := "oo, 卖出buy In<----限价单"

				if i < nselltimes/2 {
					arrsellTradePrice[i] = nsellprice - float64(i)*splitnsellinterval
				} else {
					arrsellTradePrice[i] = nsellprice + float64((i-nselltimes/2))*splitnsellinterval
				}

				tradePrice := fmt.Sprintf("%f", arrsellTradePrice[i])
				strsplitTradeAmount := fmt.Sprintf("%f", splitbuyTradeAmount)

				ret = tradeAPI.Sell(tradePrice, strsplitTradeAmount)

				if ret != "0" {
					fmt.Fprint(res, "交易委托成功")
				} else {
					fmt.Fprint(res, "交易委托失败")
				}
				logger.Infoln(warning)
			}
		}
	})

	m.Use(auth.Basic(SecretOption["username"], SecretOption["password"]))
	m.Use(martini.Static("./static"))
	m.Use(martini.Static("../static"))

	logger.Infoln(http.ListenAndServe(Config["host"], m))

	m.Run()

	fmt.Println("[ ---------------------------------------------------------->>> ")
	fmt.Printf("start web server failed, please check if %s is already used.", Config["host"])
	fmt.Println(" <<<----------------------------------------------------------] ")
}
Esempio n. 6
0
//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
}
Esempio n. 7
0
//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
}
Esempio n. 8
0
//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
}
Esempio n. 9
0
func SendEmail(warning string) {
	if !GetBacktest() {
		go email.TriggerTrender(warning)
	}
}
Esempio n. 10
0
//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
		}
	*/

	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)
	MACDdif := getMACDdif(emaShort, emaLong)
	MACDSignal := getMACDSignal(MACDdif, signalPeriod)
	MACDHistogram := getMACDHistogram(MACDdif, MACDSignal)

	length := len(Price)

	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) ||
		(macdStrategy.PrevMACDTrade == "sell" && MACDHistogram[length-2] > 0.000001 && MACDHistogram[length-1] > MACDbuyThreshold) {
		if Option["enable_trading"] == "1" && macdStrategy.PrevMACDTrade != "buy" {
			macdStrategy.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]), tradeAmount) != "0" {
				macdStrategy.PrevBuyPirce = Price[length-1]
				warning += "[委托成功]"
			} else {
				warning += "[委托失败]"
			}

			go email.TriggerTrender(warning)
		}
	} else if (MACDHistogram[length-2] > 0.000001 && MACDHistogram[length-1] < MACDsellThreshold) ||
		(macdStrategy.PrevMACDTrade == "buy" && MACDHistogram[length-2] < -0.000001 && MACDHistogram[length-1] < MACDsellThreshold) {
		if Option["enable_trading"] == "1" && macdStrategy.PrevMACDTrade != "sell" {
			macdStrategy.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]), tradeAmount) != "0" {
				warning += "[委托成功]"
			} else {
				warning += "[委托失败]"
			}

			go email.TriggerTrender(warning)
		}
	}

	//do sell when price is below stoploss point
	if Price[length-1] < macdStrategy.PrevBuyPirce*(1-stoploss*0.01) {
		if Option["enable_trading"] == "1" && macdStrategy.PrevMACDTrade != "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 += "[委托成功]"
			} else {
				warning += "[委托失败]"
			}

			go email.TriggerTrender(warning)

			macdStrategy.PrevMACDTrade = "sell"
			macdStrategy.PrevBuyPirce = 0
		}
	}

	return true
}
Esempio n. 11
0
//MACD strategy
func (macdStrategy *MACDStrategy) Perform(tradeAPI TradeAPI, Time []string, Price []float64, Volumn []float64) 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
		}
	*/

	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
	}

	//compute the indictor
	emaShort := EMA(Price, shortEMA)
	emaLong := EMA(Price, longEMA)
	MACDdif := getMACDdif(emaShort, emaLong)
	MACDSignal := getMACDSignal(MACDdif, signalPeriod)
	MACDHistogram := getMACDHistogram(MACDdif, MACDSignal)

	length := len(Price)

	if MACDdif[length-1] != macdStrategy.PrevMACDdif {
		macdStrategy.PrevMACDdif = MACDdif[length-1]
		logger.Infof("MACD:d%5.03f\ts%5.03f\th%5.03f\tPrice:%5.02f\n", MACDdif[length-1], MACDSignal[length-1], MACDHistogram[length-1], Price[length-1])
	}

	//macd cross
	if (MACDHistogram[length-2] < -0.000001 && MACDHistogram[length-1] > MACDbuyThreshold) ||
		(macdStrategy.PrevMACDTrade == "sell" && MACDHistogram[length-2] > 0.000001 && MACDHistogram[length-1] > MACDbuyThreshold) {
		if Option["disable_trading"] != "1" && macdStrategy.PrevMACDTrade != "buy" {
			macdStrategy.PrevMACDTrade = "buy"

			histogram := fmt.Sprintf("%0.03f", MACDHistogram[length-1])
			warning := "MACD up cross, 买入buy In<----市价" + tradeAPI.GetTradePrice("") +
				",委托价" + tradeAPI.GetTradePrice("buy") + ",histogram" + histogram
			logger.Infoln(warning)
			if tradeAPI.Buy(tradeAPI.GetTradePrice("buy"), tradeAmount) {
				macdStrategy.PrevBuyPirce = Price[length-1]
				warning += "[委托成功]"
			} else {
				warning += "[委托失败]"
			}

			go email.TriggerTrender(warning)
		}
	} else if (MACDHistogram[length-2] > 0.000001 && MACDHistogram[length-1] < MACDsellThreshold) ||
		(macdStrategy.PrevMACDTrade == "buy" && MACDHistogram[length-2] < -0.000001 && MACDHistogram[length-1] < MACDsellThreshold) {
		if Option["disable_trading"] != "1" && macdStrategy.PrevMACDTrade != "sell" {
			macdStrategy.PrevMACDTrade = "sell"

			histogram := fmt.Sprintf("%0.03f", MACDHistogram[length-1])
			warning := "MACD down cross, 卖出Sell Out---->市价" + tradeAPI.GetTradePrice("") +
				",委托价" + tradeAPI.GetTradePrice("sell") + ",histogram" + histogram
			logger.Infoln(warning)
			if tradeAPI.Sell(tradeAPI.GetTradePrice("sell"), tradeAmount) {
				warning += "[委托成功]"
			} else {
				warning += "[委托失败]"
			}

			go email.TriggerTrender(warning)
		}
	}

	//do sell when price is below stoploss point
	if Price[length-1] < macdStrategy.PrevBuyPirce*(1-stoploss*0.01) {
		if Option["disable_trading"] != "1" && macdStrategy.PrevMACDTrade != "sell" {
			macdStrategy.PrevMACDTrade = "sell"
			macdStrategy.PrevBuyPirce = 0
			warning := "stop loss, 卖出Sell Out---->市价" + tradeAPI.GetTradePrice("") + ",委托价" + tradeAPI.GetTradePrice("sell")
			logger.Infoln(warning)
			if tradeAPI.Sell(tradeAPI.GetTradePrice("sell"), tradeAmount) {
				warning += "[委托成功]"
			} else {
				warning += "[委托失败]"
			}

			go email.TriggerTrender(warning)
		}
	}

	return true
}
Esempio n. 12
0
//KDJ-EX strategy
func (kdjex *KDJexStrategy) Tick(records []Record) bool {

	const btcslap = 0.2
	const ltcslap = 0.01
	const timeout = 300 //s
	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
	}

	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)
			//fmt.Println(ret, orderbook)

			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)
				} 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")
			}

			go email.TriggerTrender(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)
				} else {
					warning += "[委托失败]"
				}

				logger.Infoln(warning)
			}

			kdjex.SellBegin = time.Now()
			kdjex.PrevKDJTrade = "sell"

			_, ret = GetAccount()

			if !ret {
				logger.Infoln("GetAccount failed")
			}
			go email.TriggerTrender(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)
			if sell(getTradePrice("sell", Price[length-1]), tradeAmount) != "0" {
				warning += "[委托成功]"
			} else {
				warning += "[委托失败]"
				for i := 1; i <= ordercount; i++ {
					warning := "stop loss, 卖出Sell Out---->限价单"
					sellID := sell(getTradePrice("sell", Price[length-1]), splitTradeAmount)
					if sellID != "0" {
						warning += "[委托成功]"
						kdjex.SellId = append(kdjex.SellId, sellID)
					} else {
						warning += "[委托失败]"
					}

					logger.Infoln(warning)
				}
			}

			kdjex.SellBegin = time.Now()
			kdjex.PrevKDJTrade = "sell"

			_, ret := GetAccount()

			if !ret {
				logger.Infoln("GetAccount failed")
			}
			go email.TriggerTrender(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
}
Esempio n. 13
0
//EMA strategy
func (emaStrategy *EMAStrategy) Tick(records []Record) bool {
	//read config
	shortEMA, _ := strconv.Atoi(Option["shortEMA"])
	longEMA, _ := strconv.Atoi(Option["longEMA"])

	_, err := strconv.ParseFloat(Option["tradeAmount"], 64)
	if err != nil {
		logger.Errorln("config item tradeAmount is not float")
		return false
	}
	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)
		//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)

	length := len(Price)
	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.03f\t%0.03f\n", Price[length-1], 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" && emaStrategy.PrevEMATrade != "buy" {

				emaStrategy.PrevEMACross = "up"

				if emaStrategy.checkThreshold("buy", EMAdif[length-1]) {

					emaStrategy.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" {
						emaStrategy.PrevBuyPirce = Price[length-1]
						warning += "[委托成功]"
					} else {
						warning += "[委托失败]"
					}

					go email.TriggerTrender(warning)
				}
			}
		}

		//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" && emaStrategy.PrevEMATrade != "sell" {

				if emaStrategy.checkThreshold("sell", EMAdif[length-1]) {

					emaStrategy.PrevEMATrade = "sell"

					var tradePrice string
					if Option["discipleMode"] == "1" {
						stoplossPrice := emaStrategy.PrevBuyPirce * (1 - stoploss*0.01)
						if Price[length-1] > stoplossPrice {
							tradePrice = getTradePrice("sell", Price[length-1])
						} else {
							discipleValue, err := strconv.ParseFloat(Option["discipleValue"], 64)
							if err != nil {
								logger.Errorln("config item discipleValue is not float")
								return false
							}

							tradePrice = fmt.Sprintf("%f", emaStrategy.PrevBuyPirce+discipleValue)
						}
					} else {
						tradePrice = getTradePrice("sell", Price[length-1])
					}

					diff := fmt.Sprintf("%0.03f", EMAdif[length-1])
					warning := "EMA down cross, 卖出Sell Out---->市价" + getTradePrice("", Price[length-1]) +
						",委托价" + tradePrice + ",diff" + diff

					logger.Infoln(warning)
					if Sell(tradePrice, tradeAmount) != "0" {
						warning += "[委托成功]"
					} else {
						warning += "[委托失败]"
					}

					go email.TriggerTrender(warning)
				}
			}
		}

		//backup the kline data for analyze
		if Config["env"] == "dev" {
			backup(Time[length-1])
		}
	}

	//do sell when price is below stoploss point
	stoplossPrice := emaStrategy.PrevBuyPirce * (1 - stoploss*0.01)
	if Price[length-1] <= stoplossPrice {
		if Option["enable_trading"] == "1" && emaStrategy.PrevEMATrade != "sell" {
			emaStrategy.PrevEMATrade = "sell"
			var tradePrice string
			if Option["discipleMode"] == "1" {
				if Price[length-1] > stoplossPrice {
					tradePrice = getTradePrice("sell", Price[length-1])
				} else {
					discipleValue, err := strconv.ParseFloat(Option["discipleValue"], 64)
					if err != nil {
						logger.Errorln("config item discipleValue is not float")
						return false
					}

					tradePrice = fmt.Sprintf("%f", emaStrategy.PrevBuyPirce+discipleValue)
				}
			} else {
				tradePrice = getTradePrice("sell", Price[length-1])
			}

			warning := "stop loss, 卖出Sell Out---->市价" + getTradePrice("", Price[length-1]) + ",委托价" + tradePrice
			logger.Infoln(warning)
			if Sell(tradePrice, tradeAmount) != "0" {
				warning += "[委托成功]"
			} else {
				warning += "[委托失败]"
			}

			emaStrategy.PrevBuyPirce = 0
			go email.TriggerTrender(warning)
		}
	}

	return true
}
Esempio n. 14
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
}