private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { string reportStr = ""; try { var account = robotTrade.CurrentAccount; var ticker = robotMarket.GetTicker(info.Symbol); if (DateTime.Now.Minute == 0) { //整点日志 reportStr = GetReport(info, account, ticker, true); } else { //分钟日志 reportStr = GetReport(info, account, ticker, false); } Log4NetUtility.Info("ReportDetail ", reportStr); } catch (Exception ex) { Log4NetUtility.Error("ReportTimer", Utils.Exception2String(ex)); } }
public static List <CoinConfig> Load() { try { string conFilePath = AppDomain.CurrentDomain.BaseDirectory + "CoinConfigs.json"; if (!File.Exists(conFilePath)) { throw (new Exception("CoinConfigs配置文件不存在")); } StreamReader sr = new StreamReader(conFilePath, Encoding.Default); string jsonStr = sr.ReadToEnd(); var list = JsonConvert.DeserializeObject <List <CoinConfig> >(jsonStr); if (list != null && list.Count > 0) { Log4NetUtility.Info("加载系统配置", "已成功加载系统配置CoinConfigs"); return(list); } else { throw (new Exception("CoinConfigs配置文件异常")); } } catch (Exception e) { Log4NetUtility.Error("加载系统配置CoinConfigs", "加载配置异常:" + Utils.Exception2String(e)); throw (e); } }
//private void SetTradeQty(bool firststart = false) //{ // if (firststart && config.TradeQty != null && config.TradeQty != 0) // { // info.TradeQty = (decimal)config.TradeQty; // } // else // { // var info = coinConfigs.FirstOrDefault(a => a.Platform == Platform && a.Symbol == Symbol); // var ticker = GetTicker(); // var account = GetAccount(); // decimal price_now = ticker.last; // decimal net = account.GetNet(this.info.Symbol, price_now); // int packetNum = (this.info.OrderQty + 3) * 2; // decimal newTradeQTY = info.FormatAmount2D(net / price_now / packetNum); // this.info.TradeQty = newTradeQTY; // } //} private void resetAccount(string side, decimal resetAmt) { Stopwatch stopwatch_market = new Stopwatch(); stopwatch_market.Start(); bool result_market = false; for (int i = 0; i < 3 && !result_market; i++) { var ticker = GetTicker(); decimal price = side == "buy" ? ticker.sell : ticker.buy; //Trade trade = robotTrade.Trade(Symbol, side, price, resetAmt); Trade trade = robotTrade.MarketTrade(Symbol, side, price, resetAmt); result_market = trade.result; if (result_market) { stopwatch_market.Stop(); //UpdateMarketFee(trade.order_id); Log4NetUtility.Info("初始资源", $"《市价{side}》,当前Price:{ticker.last.ToString("#0.00")},Deal数量:{resetAmt.ToString("#0.0000")},市价用时:{stopwatch_market.ElapsedMilliseconds}"); Thread.Sleep(3000); break; } else { Thread.Sleep(1000); if (trade.error_code.Contains("1002")) { Thread.Sleep(2000 * i); //i -= 1; } } } }
private void CancelOrder(Order order) { CancelOrder cancel = robotTrade.CancelOrder(Symbol, order.order_id); if (cancel.result) { robotSession.RemoveSessionOrder(order); //DbHelper.DBSaveChange(doubleorder, "UpDate"); Log4NetUtility.Info("RobotHFT", "Canceled Order Success. id:" + Utils.ShortID(order.order_id) + " Price:" + order.price); } else { string errmsg = cancel.error_code + " " + cancel.msg; if (cancel.error_code.Contains("3008")) { robotSession.RemoveSessionOrder(order); //sessionOrders.Remove(doubleorder); ////DbHelper.CreateInstance().RemoveOrder(doubleorder); errmsg = "已清除脏数据Order。id:" + Utils.ShortID(order.order_id) + " Price:" + order.price; } else { //errmsg = "撤销重复Order失败。id:" + Utils.ShortID(doubleorder.order_id) + " msg:" + cancel.error_code + cancel.msg; } Log4NetUtility.Info("CancelOrder", errmsg); //DbHelper.CreateInstance().AddErrInfo("缓存单验证", errmsg); } }
/// <summary> /// 全仓挂单 /// </summary> private void HangOrders() { try { #region 新缓存列表 newSessionOrders List <Order> newSessionOrders = new List <Order>(); decimal newFloatPrice = GetStandardPrice(GetTicker().last); info.floatPrice = newFloatPrice; info.buyOrderCount = info.sellOrderCount = info.OrderQty; //info.ShockCount_tmp = info.UpCount_tmp = info.DownCount_tmp = 0; for (int i = 1; i <= info.buyOrderCount; i++) { decimal orderprice = newFloatPrice - i * info.SpanPrice; Order order = new Order() { price = orderprice, amount = info.TradeQty, type = "buy" }; newSessionOrders.Add(order); } for (int i = 1; i <= info.sellOrderCount; i++) { decimal orderprice = newFloatPrice + i * info.SpanPrice; Order order = new Order() { price = orderprice, amount = info.TradeQty, type = "sell" }; newSessionOrders.Add(order); } #endregion #region 挂单、缓存 Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); robotSession.ClearSessionAllOrders(); foreach (var addOrder in newSessionOrders) { TradeOrder(addOrder); Thread.Sleep(250); } //Parallel.ForEach(newSessionOrders, addOrder => //{ // TradeOrder(addOrder); //}); stopwatch.Stop(); Log4NetUtility.Info("HangOrders", robotSession.LogSring()); Log4NetUtility.Info("HangOrders", $"Order中间价:{newFloatPrice}。交易总用时(毫秒):{stopwatch.ElapsedMilliseconds}"); #endregion } catch (Exception e) { Log4NetUtility.Error("HangOrders", Utils.Exception2String(e)); DbHelper.CreateInstance().AddError("HangOrders", e); } }
private Trade TradeOrder(Order order) { if (order == null) { return(null); } Trade trade = robotTrade.Trade(Symbol, order.type, order.price, order.amount); for (int i = 0; i < 3; i++) { if (trade.result && !string.IsNullOrEmpty(trade.order_id)) { order.order_id = trade.order_id; order.create_date = Utils.GetUtcTimeDec(); robotSession.AddUpdateSessionOrder(order); Log4NetUtility.Debug($"New 《{order.type}》 Price:{order.price.ToString("#0.0000")} id:{Utils.ShortID(order.order_id)}"); break; } else { string type = order.type == "buy" ? "-S" : "+B"; Log4NetUtility.Info("RobotHFT", $"《{type}》委托失败,P:《{order.price.ToString("#0.00")}》A:《{order.amount.ToString("#0.0000")}》,第{i + 1}次返回:{trade.error_code} {trade.msg}"); Thread.Sleep(1000); if (trade.error_code.Contains("1002")) { Thread.Sleep(2000 * i); //i -= 1; } if (trade.error_code.Contains("1016")) { var side = order.type == "buy" ? "sell" : "buy"; var ticker = robotMarket.GetTicker(Symbol); decimal price = side == "buy" ? ticker.sell : ticker.buy; Trade tradeM = robotTrade.MarketTrade(Symbol, side, price, order.amount); if (tradeM.result) { Log4NetUtility.Info("RobotHFT", $"《{side}》市价调整,P:《{price.ToString("#0.00")}》A:《{order.amount.ToString("#0.0000")}》 "); } else { Log4NetUtility.Info("RobotHFT", $"《{side}》市价失败,P:《{price.ToString("#0.00")}》A:《{order.amount.ToString("#0.0000")}》 {tradeM.error_code} {tradeM.msg}"); } Thread.Sleep(2000 * i); } } } return(trade); }
public void Run() { robotMarket.Run(new List <string>() { Symbol }); Log4NetUtility.Info("Robot_Market", "已开始运行"); robotTrade.Run(); Log4NetUtility.Info("Robot_Trade", "已开始运行"); //RobotHFT Start Start(true); robotSession.Run(); Log4NetUtility.Info("Robot_Session", "已开始运行"); robotCurrent.Run(); Log4NetUtility.Info("Robot_Current", "已开始运行"); robotReport.Run(); Log4NetUtility.Info("Robot_Report", "已开始运行"); Log4NetUtility.Info("RobotHFT", "已开始运行"); }
/// <summary> /// 撤消当前挂单 /// </summary> /// <returns></returns> private int ClearAllCurrentOrders(string symbol) { Stopwatch stopwatch_cancel = new Stopwatch(); stopwatch_cancel.Start(); int count = robotTrade.ClearCurrentOrders(symbol); while (count == -1) { count = robotTrade.ClearCurrentOrders(symbol); Thread.Sleep(1000); } stopwatch_cancel.Stop(); if (count > 0) { Thread.Sleep(2000); } robotSession.ClearSessionAllOrders(); Log4NetUtility.Info("ClearAllCurrentOrders", $"撤单当前委托 {count}个, 共用时:{ stopwatch_cancel.ElapsedMilliseconds}"); return(count); }
public static Config LoadConfig() { try { Log4NetUtility.Info("加载系统配置", "开始加载系统配置"); string conFilePath = AppDomain.CurrentDomain.BaseDirectory + "config.json"; if (!File.Exists(conFilePath)) { throw (new Exception("配置文件不存在")); } StreamReader sr = new StreamReader(conFilePath, Encoding.Default); string jsonStr = sr.ReadToEnd(); Config SysConfig = JsonConvert.DeserializeObject <Config>(jsonStr); Log4NetUtility.Info("加载系统配置", "已成功加载系统配置"); return(SysConfig); } catch (Exception e) { Log4NetUtility.Error("加载系统配置", "加载配置异常:" + Utils.Exception2String(e)); throw (e); } }
private int ClearCurrentOrders_FC(string symbol) { Orders orders = GetCurrentOrders_FC(symbol); if (!orders.result) { return(-1); } int ClearedCount = 0; Parallel.ForEach(orders.orders, order => { decimal cancelPrice = order.price; string ordertype = order.type == "buy" ? "+B" : "-S"; for (int i = 1; i <= 3; i++) { CancelOrder cancel = tradeHepler.CancelOrder_FC(order.order_id); if (cancel.result) { ClearedCount++; string msg = $"{ordertype} P:{cancelPrice.ToString("0.00")} ID:{order.order_id}"; Log4NetUtility.Info("ClearOrders", msg); break; } else { string msg = $"{i} {ordertype} P:{cancelPrice.ToString("0.00")} ID:{order.order_id} Msg:{cancel.error_code} {cancel.msg}"; Log4NetUtility.Info("ClearOrders", msg); Thread.Sleep(250); } } }); currentOrdersDic.Remove(symbol); return(ClearedCount); }
private void CheckSessionOrders(long dotime) { #region if (SessionOrders.Count == 0 && Running) { return; } if (CheckSessionDoTime == -1) { lock (objectLock) { if (CheckSessionDoTime == -1) { CheckSessionDoTime = dotime; } } } #endregion if (CheckSessionDoTime == dotime) { try { //判断Order与缓存验证互斥操作 lock (SessionOrders) { if (SessionOrders.Count == 0 && Running) { return; } Running = true; #region 撤销重复 var doubleorder = SessionOrders.FirstOrDefault(b => SessionOrders.Exists(a => a.price == b.price && a.type == b.type && a.order_id != b.order_id)); if (doubleorder != null) { Log4NetUtility.Info("", "存在重复缓存单 Price:" + doubleorder.price); //string msg = ""; #region CancelOrder CancelOrder cancel = robotTrade.CancelOrder(symbol, doubleorder.order_id); if (cancel.result) { SessionOrders.Remove(doubleorder); doubleorder.status = "3"; //DbHelper.DBSaveChange(doubleorder, "UpDate"); Log4NetUtility.Info("缓存单验证", "已撤销重复Order。id:" + Utils.ShortID(doubleorder.order_id) + " Price:" + doubleorder.price); CheckSessionDoTime = -1; return; } else { string errmsg = ""; if (cancel.error_code.Contains("3008")) { SessionOrders.Remove(doubleorder); //DbHelper.CreateInstance().RemoveOrder(doubleorder); errmsg = "已清除脏数据Order。id:" + Utils.ShortID(doubleorder.order_id) + " Price:" + doubleorder.price; } else { errmsg = "撤销重复Order失败。id:" + Utils.ShortID(doubleorder.order_id) + " msg:" + cancel.error_code + cancel.msg; } Log4NetUtility.Info("缓存单验证", errmsg); //DbHelper.CreateInstance().AddErrInfo("缓存单验证", errmsg); } #endregion } #endregion #region 撤销异常价格 List <Order> errPriceOrders = SessionOrders.Where(a => a.price < 50m).ToList(); if (errPriceOrders.Count > 0) { foreach (var order in errPriceOrders) { Log4NetUtility.Info("", "存在异常价格存单 Price:" + order.price); #region CancelOrder CancelOrder cancel = robotTrade.CancelOrder(symbol, order.order_id); if (cancel.result) { SessionOrders.Remove(order); order.status = "3"; //DbHelper.DBSaveChange(doubleorder, "UpDate"); Log4NetUtility.Info("缓存单验证", "已撤销重复Order。id:" + Utils.ShortID(order.order_id) + " Price:" + order.price); } else { string errmsg = ""; if (cancel.error_code.Contains("3008")) { SessionOrders.Remove(order); //DbHelper.CreateInstance().RemoveOrder(doubleorder); errmsg = "已清除脏数据Order。id:" + Utils.ShortID(order.order_id) + " Price:" + order.price; } else { errmsg = "撤销重复Order失败。id:" + Utils.ShortID(doubleorder.order_id) + " msg:" + cancel.error_code + cancel.msg; } Log4NetUtility.Info("缓存单验证", errmsg); //DbHelper.CreateInstance().AddErrInfo("缓存单验证", errmsg); } #endregion } CheckSessionDoTime = -1; return; } #endregion #region 调整订单数量 if return int buycount = SessionOrders.Count(a => a.type == "buy"); int sellcount = SessionOrders.Count(a => a.type == "sell"); int deff = buycount + sellcount - mainData.buyOrderCount - mainData.sellOrderCount; #region 多单 return if (deff > 0) { Log4NetUtility.Info("MoreOrder", string.Format("Order数大于初始值,现值:{0} 初始:{1}", buycount + sellcount, mainData.buyOrderCount + mainData.sellOrderCount)); Order cancelOrder; if (buycount > sellcount) { cancelOrder = SessionOrders.OrderBy(a => a.price).First(); } else { cancelOrder = SessionOrders.OrderBy(a => a.price).Last(); } //string msg = ""; CancelOrder cancel = robotTrade.CancelOrder(symbol, cancelOrder.order_id); if (cancel.result) { SessionOrders.Remove(cancelOrder); cancelOrder.status = "3"; //DbHelper.DBSaveChange(cancelOrder, "UpDate"); string errmsg = string.Format("已撤 {0} id:{1}, Price:{2}", cancelOrder.type == "buy" ? "+B" : "-S", Utils.ShortID(cancelOrder.order_id), cancelOrder.price.ToString("0.00")); //DbHelper.CreateInstance().AddErrInfo("缓存单验证", errmsg); Log4NetUtility.Info("MoreOrder", errmsg); } CheckSessionDoTime = -1; return; } #endregion #region 少单 return if (deff < 0) { Log4NetUtility.Info("LessOrder", string.Format("Order数小于初始值,现值{0} 初始{1}", buycount + sellcount, mainData.buyOrderCount + mainData.sellOrderCount)); account = helper.GetUserInfo(Platform); decimal price = 0; //string msg = ""; string errmsg = ""; string type = ""; if (account.GetFreeCoin(Symbol) * ticker.last > account.GetFreeFund()) { price = SessionOrders.OrderBy(a => a.price).Last().price + mainData.SpanPrice; type = "sell"; } else { price = SessionOrders.OrderBy(a => a.price).First().price - mainData.SpanPrice; type = "buy"; } Trade trade = helper.PostTrade(Symbol, type, price, mainData.TradeQty, Platform); //Trade trade = helper.PostTrade_FC(Symbol, type, "limit", price.ToString("0.00"), mainData.TradeQty.ToString("0.000")); if (trade.result && !string.IsNullOrEmpty(trade.order_id)) { var addorder = new var(trade.order_id, price, mainData.TradeQty, type); addorder.order_time = Utils.GetDateTimeDec(); SessionOrders.Add(addorder); //DbHelper.DBSaveChange(addorder, "Add"); errmsg = string.Format("已补充不足Order。 《{0}》Price:{1}", type == "buy" ? "+B" : "-S", price); } else { errmsg = string.Format("补充不足Order失败。《{0}》Price:{1}", type == "buy" ? "+B" : "-S", price); } Log4NetUtility.Info("LessOrder", errmsg); //DbHelper.CreateInstance().AddErrInfo("缓存单验证", errmsg); CheckSessionDoTime = -1; return; } #endregion #endregion #region 判断补充丢单 if return var lessorder = GetLossOrder(); if (lessorder != null) { string errmsg = ""; //string msg = ""; //bool deal = false; //if (lessorder.type == "buy") //{ // deal = TradeHelper.CreateDelegateBuy(lessorder.order_amount, lessorder.price, ref msg); //} //if (lessorder.type == "sell") //{ // deal = TradeHelper.CreateDelegateSell(lessorder.order_amount, lessorder.price, ref msg); //} Trade trade = helper.PostTrade(Symbol, lessorder.type, lessorder.price, lessorder.order_amount, Platform); //Trade trade = helper.PostTrade_FC(Symbol, lessorder.type, "limit", lessorder.price.ToString("0.00"), lessorder.order_amount.ToString("0.000")); if (trade.result && !string.IsNullOrEmpty(trade.order_id)) { lessorder.order_id = trade.order_id; //lessorder.order_time = DateTime.Now.Ticks; SessionOrders.Add(lessorder); //DbHelper.DBSaveChange(lessorder, "Add"); errmsg = string.Format("AddOrder {0},ID:{1},Price:{2}", lessorder.type == "buy" ? "《+B》" : "《-S》", Utils.ShortID(lessorder.order_id), lessorder.price.ToString("0.00")); } else { errmsg = $"AddOrder {lessorder.type} Fail! {lessorder.type } Price:{lessorder.price},ErrMsg: {trade.error_code} {trade.msg}"; //errmsg = string.Format("AddOrder{0} Fail,ID:{1},Price:{2},ErrMsg: {3} {4}", lessorder.type == "buy" ? "《+B》" : "《-S》", lessorder.order_id.Remove(5, trade.order_id.Count() - 6), lessorder.price, trade.error_code, trade.msg); } Log4NetUtility.Info("LossOrder", errmsg); //DbHelper.CreateInstance().AddErrInfo("判断补充丢单", errmsg); CheckSessionDoTime = -1; return; } #endregion #region 判断单边、平仓 //if (filledSessionOrders.Count == 0) // return; var lastFilledOrderTime = filledSessionOrders.Max(a => a.order_time); //if (buycount == 0 || sellcount == 0 || Utils.GetDateTimeDec(-1000) < lastFilledOrderTime ) if (buycount == 0 || sellcount == 0) { if (Utils.GetDateTimeDec(-180) < lastFilledOrderTime) { return; } //平仓统计 //mainData.floatPrice = order.price; mainData.resetCount += 1; string timeStr = DateTime.Now.ToString("yyyyMMddHHmmss"); ResetTimes.Add(double.Parse(timeStr)); try { ReSetOrder(buycount == 0 ? "sell" : "buy"); } catch (Exception e) { ////DbHelper.CreateInstance().AddErrInfo("全包平仓异常", e); Log4NetUtility.Error("全包平仓异常", e.Message); Log4NetUtility.Error("全包平仓异常", e.StackTrace); } } #endregion } } catch (Exception e) { //DbHelper.CreateInstance().AddErrInfo("缓存验证", e); Log4NetUtility.Error("缓存验证", e.Source); Log4NetUtility.Error("缓存验证", e.Message); Log4NetUtility.Error("缓存验证", e.StackTrace); } finally { CheckSessionDoTime = -1; Running = false; } } }
/// <summary> /// 是否调参(平仓过多) /// </summary> /// <param name="ResetTimes"></param> /// <param name="ShockTimes"></param> /// <param name="lastReStartTime"></param> /// <returns></returns> public void CheckTroppoReset(List <decimal> ResetTimes, List <decimal> ShockTimes, DateTime lastReStartTime) { try { #region 1 分钟内平仓大于等于2次 decimal minu = Utils.GetUtcTimeDec(-1 * 60); ////最后一次震荡1分钟内,不检测返回 if (ResetTimes.Max() > minu) { return; } int resetcount = ResetTimes.Count(a => a > minu); //一分钟内平仓大于2次,振幅增大 if (resetcount >= 2) { info.SpanPrice = info.SpanPrice * 2; Log4NetUtility.Info("判断平仓过频繁", "大包/大振幅时.1 分钟内平仓大于等于2次! SpanPrice * 2:{info.SpanPrice}"); return; } #endregion #region 2 分钟内平仓大于等于2次(调参1分钟内忽略) if (lastReStartTime.AddMinutes(1) < DateTime.Now) { minu = Utils.GetUtcTimeDec(-2 * 60); resetcount = ResetTimes.Count(a => a > minu); if (resetcount >= 2) { info.SpanPrice = info.SpanPrice * 2; Log4NetUtility.Info("判断平仓过频繁", "大包/大振幅时.2 分钟内平仓大于等于2次! SpanPrice * 2:{info.SpanPrice}"); return; } } #endregion #region //3 分钟内平仓大于等于5次(调参2分钟内忽略) //if (lastReStartTime.AddMinutes(2) < DateTime.Now) //{ // minu = Utils.GetDateTimeDec(-3 * 60); // resetcount = ResetTimes.Count(a => a > minu); // if (resetcount >= 5) // { // info.SpanPrice = info.SpanPrice * 2; // Log4NetUtility.Info("判断平仓过频繁", "大包/大振幅时.3 分钟内平仓大于等于5次! SpanPrice * 2:{info.SpanPrice}"); // return; // } //} #endregion #region 5 分钟内平仓大于等于3次(调参2分钟内忽略) if (lastReStartTime.AddMinutes(2) < DateTime.Now) { minu = Utils.GetUtcTimeDec(-5 * 60); resetcount = ResetTimes.Count(a => a > minu); if (resetcount >= 3) { info.SpanPrice = info.SpanPrice * 2; Log4NetUtility.Info("判断平仓过频繁", "大包/大振幅时.5 分钟内平仓大于等于3次! SpanPrice * 2:{info.SpanPrice}"); return; } } #endregion #region //7 分钟内平仓大于等于7次 //minu = Utils.GetDateTimeDec(-8 * 60); //resetcount = ResetTimes.Count(a => a > minu); //if (resetcount >= 7) //{ // info.SpanPrice = info.SpanPrice * 2; // Log4NetUtility.Info("判断平仓过频繁", "大包/大振幅时.7 分钟内平仓大于等于7次! SpanPrice * 2:{info.SpanPrice}"); // return; //} #endregion #region 10分钟内平仓大于等于4次 minu = Utils.GetUtcTimeDec(-10 * 60); resetcount = ResetTimes.Count(a => a > minu); if (resetcount >= 4) { info.SpanPrice = info.SpanPrice * 2; Log4NetUtility.Info("判断平仓过频繁", "大包/大振幅时.10分钟内平仓大于等于4次! SpanPrice * 2:{info.SpanPrice}"); return; } #endregion #region 交易/平仓< 25 int count = ResetTimes.Count(); //if (count >= 2 && info.SpanPrice < 1) if (count >= 2) { //decimal lasttime = ResetTimes.OrderBy(a => a).ToList()[count - 2]; decimal lasttime = ResetTimes.Max(); int scount = ShockTimes.Count(a => a > lasttime); if (scount < 25) { info.SpanPrice = info.SpanPrice * 2; Log4NetUtility.Info("判断平仓过频繁", $"交易/平仓:{scount}<25. SpanPrice * 2:{info.SpanPrice}"); } } #endregion } catch (Exception e) { Log4NetUtility.Error("CheckTroppoReset", Utils.Exception2String(e)); DbHelper.CreateInstance().AddError("CheckTroppoReset", e); } }
/// <summary> /// 全量平仓 /// </summary> private void ReSetOrder(bool isParaReset = false) { try { if (resetflag) { return; } resetflag = true; robotSession.Stop(); robotCurrent.Stop(); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); Log4NetUtility.Info("SessionEvent", "************************* 全量平仓<开始> ************************"); if (!isParaReset) { info.resetCount++; } info.lastReStartTime = DateTime.Now; info.ResetTimes.Add(Utils.GetUtcTimeDec()); //CheckTroppoReset(info.ResetTimes, info.ShockTimes, info.lastReStartTime); var coin = coinConfigs.FirstOrDefault(a => a.Symbol == Symbol); info.SpanPrice = GetSpanPrice(coin.BasePriceWidth); Start(); stopwatch.Stop(); #region 清除计数缓存 decimal timeDoub = Utils.GetUtcTimeDec(-60 * 30); info.ShockTimes.RemoveAll(a => a <= timeDoub); info.ResetTimes.RemoveAll(a => a <= timeDoub); int scount = info.ShockTimes.Count - 800; int rcount = info.ResetTimes.Count - 100; if (scount > 0) { info.ShockTimes.RemoveRange(0, scount); } if (rcount > 0) { info.ResetTimes.RemoveRange(0, rcount); } #endregion //info.ShockCount_tmp = info.UpCount_tmp = info.DownCount_tmp = 0; Log4NetUtility.Info("SessionEvent", $"*************************全量平仓<结束>耗时:{stopwatch.ElapsedMilliseconds}******************"); } catch (Exception e) { Log4NetUtility.Error("SessionEvent", Utils.Exception2String(e)); DbHelper.CreateInstance().AddError("SessionEvent", e); } finally { resetflag = false; robotSession.Run(); robotCurrent.Run(); } }
/// <summary> /// 市价平衡资源 /// </summary> /// <param name="firststart"></param> private void ResetAccount(bool firststart = false) { string side = ""; decimal reset_amt = 0; var coininfo = coinConfigs.FirstOrDefault(a => a.Platform == Platform && a.Symbol == Symbol); var ticker = GetTicker(); var account = GetAccount(); if (firststart && config.TradeQty != null && config.TradeQty != 0) { info.TradeQty = (decimal)config.TradeQty; } else { decimal price_now = ticker.last; decimal net = account.GetNet(this.info.Symbol, price_now); int packetNum = (this.info.OrderQty + 3) * 2; decimal newTradeQTY = coininfo.FormatAmount2D(net / price_now / packetNum); this.info.TradeQty = newTradeQTY; } decimal coin = account.GetFreeCoin(Symbol); decimal coinUSDT = account.GetFreeFund(); var needcoin = this.info.TradeQty * (this.info.OrderQty + 2); var needfund = needcoin * ticker.sell; coinUSDT = coininfo.FormatAmount2D(coinUSDT); coin = coininfo.FormatAmount2D(coin); Log4NetUtility.Info("初始资源", $"FreeFund {coininfo.CoinB}:{coinUSDT} FreeCoin {coininfo.CoinA}:{coin} "); decimal buy_qty = needcoin - coin; if (buy_qty > 1 / coininfo.AmountLimit) { reset_amt = buy_qty; side = "buy"; } decimal sell_qty = (needfund - coinUSDT) / ticker.sell; if (sell_qty > 1 / coininfo.AmountLimit) { reset_amt = sell_qty; side = "sell"; } Log4NetUtility.Info("初始资源", $"Needfund {coininfo.CoinB}:{coininfo.FormatAmount2D(needfund)} Needcoin {coininfo.CoinA}:{coininfo.FormatAmount2D(needcoin)} buy_qty:{coininfo.FormatAmount2D(buy_qty)} sell_qty:{coininfo.FormatAmount2D(sell_qty)} reset_amt:{coininfo.FormatAmount2D(reset_amt)}"); if (side != "" && reset_amt != 0) { resetAccount(side, reset_amt); } if (firststart) { ticker = GetTicker(); account = GetAccount(); decimal Open_Price = ticker.last; decimal net = account.GetNet(coininfo.Symbol, Open_Price); info.Open_Price = info.Open_Price == 0 ? Open_Price : info.Open_Price; info.Open_Fund = info.Open_Fund == 0 ? net : info.Open_Fund; info.Open_Coin = account.GetFreeCoin(Symbol) + account.GetFreezedCoin(Symbol); info.lastReStartTime = DateTime.Now; info.resetCount = 0; Log4NetUtility.Info("初始资源", $"账户信息获取完成。 可用资金 :{account.GetFreeFund().ToString("#0.0000")} 可用币:{account.GetFreeCoin(Symbol).ToString("#0.0000")},净资金:{account.GetNet(Symbol, ticker.last).ToString("#0.0000")}"); } }
/// <summary> /// 是否调参(交易过少) /// </summary> /// <param name="ResetTimes"></param> /// <param name="ShockTimes"></param> /// <returns></returns> private bool CheckLittleTrade(List <decimal> ResetTimes, List <decimal> ShockTimes) { try { ResetTimes = ResetTimes ?? new List <decimal>(); ShockTimes = ShockTimes ?? new List <decimal>(); //已为最低配置,不可调0.25 10 #region 获取统计数据 resetcount、shockcount //默认统计时间5分钟 1->0.5 int minutes = 5; //0.5振幅时统计10钟 0.5->0.25 if (info.SpanPrice <= info.Open_SpanPrice / 2) { minutes = 10; } //小于0.5振幅统计时间15分钟 10P->5P if (info.SpanPrice < info.Open_SpanPrice / 3) { minutes = 15; } //时间点minu decimal minu = Utils.GetUtcTimeDec(-minutes * 60); int resetcount = ResetTimes.Count(a => a > minu); int shockcount = ShockTimes.Count(a => a > minu); #endregion //1、若有平仓。不调参 if (resetcount > 0) { return(false); } //2、刚开始运行时间不足 if (ShockTimes.Count == 0 || ShockTimes.Min() > minu) { return(false); } //3、若震荡大于阈值,不算过小。不调参 if (minutes == 5 && shockcount >= 2) { return(false); } if (minutes == 10 && shockcount >= 5) { return(false); } if (minutes == 15 && shockcount >= 7) { return(false); } #region 获取行情数据 maxPrice、minPrice、diff、pdiff decimal diff = 0; decimal time = Utils.GetUtcTimeDec(-minutes * 60); List <Order> oreders = FilledSessionOrders.Where(a => a.create_date >= time).ToList(); if (oreders == null || oreders.Count == 0) { diff = 0; Log4NetUtility.Info("行情平缓", $"{minutes}分钟内,{resetcount}次平仓,{shockcount}次震荡,SpanPrice:{info.SpanPrice}"); return(true); } else { decimal maxPrice = oreders.Max(a => a.price); decimal minPrice = oreders.Min(a => a.price); diff = maxPrice - minPrice; //价差 } decimal pdiff = info.SpanPrice * info.OrderQty * 2; //包差 #endregion //4、行情价差小于等于包范围的1/3时。调参 if (diff <= pdiff / 3) { if (info.SpanPrice >= 0.25m)//非最小振幅 { //降振幅 //info.SpanPrice = info.SpanPrice / 2; //if (info.SpanPrice == 0.5m)//0.5->0.25时先增加包数 //{ // result.PacketNumResult = AnalyzePropertyResultEnum.Up; // result.TradeQTYResult = AnalyzePropertyResultEnum.Down; //} Log4NetUtility.Info("行情平缓", string.Format("{0}分钟内,{1}次平仓,{2}次震荡,行情价差{3},包差{4},SpanPrice:{5}", minutes, resetcount, shockcount, diff, pdiff, info.SpanPrice)); return(true); } //else//最小振幅0.25.降包、增量 //{ //result.PacketNumResult = AnalyzePropertyResultEnum.Down; //result.TradeQTYResult = AnalyzePropertyResultEnum.Up; //} //Log4NetUtility.Info("行情平缓", string.Format("{0}分钟内,{1}次平仓,{2}次震荡,行情价差{3},包差{4},SpanPrice:{5}", minutes, resetcount, shockcount, diff, pdiff, info.SpanPrice)); } } catch (Exception e) { Log4NetUtility.Error("行情平缓", Utils.Exception2String(e)); DbHelper.CreateInstance().AddError("CheckLittleTrade", e); } return(false); }
private void CheckSessionOrders(long dotime) { #region objectLock if (SessionOrders.Count == 0 && checkRunning) { return; } if (checkSessionDoTime == -1) { lock (objectLock) { if (checkSessionDoTime == -1) { checkSessionDoTime = dotime; } } } #endregion if (checkSessionDoTime == dotime) { try { //判断Order与缓存验证互斥操作 lock (sessionLock) { if (SessionOrders.Count == 0 || checkRunning) { return; } checkRunning = true; #region 判断单边、平仓 if (SessionOrders.Count == 0) { return; } var lastFilledOrderTime = SessionOrders.Max(a => a.create_date); int buycount = SessionOrders.Count(a => a.type == "buy"); int sellcount = SessionOrders.Count(a => a.type == "sell"); //if (buycount == 0 || sellcount == 0 || Utils.GetDateTimeDec(-1000) < lastFilledOrderTime ) bool Reset = false; if (buycount == 0 || sellcount == 0) { if (Utils.GetUtcTimeDec(-180) > lastFilledOrderTime) { Reset = true; Log4NetUtility.Info("Reset", $"单边3分钟"); } } if (Utils.GetUtcTimeDec(-600) > lastFilledOrderTime) { Reset = true; Log4NetUtility.Info("Reset", $"缓存静止10分钟"); } if (Reset) { SessionEvent?.Invoke(null, new SessionEventArgs(SessionEventType.Reset)); return; } #endregion #region 撤销重复 bool flag = false; var doubleorder = SessionOrders.FirstOrDefault(b => SessionOrders.Exists(a => a.price == b.price && a.type == b.type && a.order_id != b.order_id)); if (doubleorder != null) { SessionEvent?.Invoke(null, new SessionEventArgs(SessionEventType.DoubleOrder, new List <Order>() { doubleorder })); //Log4NetUtility.Info("", "存在重复缓存单 Price:" + doubleorder.price); //string msg = ""; #region //CancelOrder //CancelOrder cancel = robotTrade.CancelOrder(symbol, doubleorder.order_id); //if (cancel.result) //{ // sessionOrders.Remove(doubleorder); // doubleorder.status = "3"; // //DbHelper.DBSaveChange(doubleorder, "UpDate"); // Log4NetUtility.Info("缓存单验证", "已撤销重复Order。id:" + Utils.ShortID(doubleorder.order_id) + " Price:" + doubleorder.price); // CheckSessionDoTime = -1; // return; //} //else //{ // string errmsg = ""; // if (cancel.error_code.Contains("3008")) // { // sessionOrders.Remove(doubleorder); // //DbHelper.CreateInstance().RemoveOrder(doubleorder); // errmsg = "已清除脏数据Order。id:" + Utils.ShortID(doubleorder.order_id) + " Price:" + doubleorder.price; // } // else // { // errmsg = "撤销重复Order失败。id:" + Utils.ShortID(doubleorder.order_id) + " msg:" + cancel.error_code + cancel.msg; // } // Log4NetUtility.Info("缓存单验证", errmsg); // //DbHelper.CreateInstance().AddErrInfo("缓存单验证", errmsg); //} #endregion flag = true; } #endregion #region 撤销异常价格 List <Order> errPriceOrders = SessionOrders.Where(a => a.price < 50m).ToList(); if (errPriceOrders.Count > 0) { SessionEvent?.Invoke(null, new SessionEventArgs(SessionEventType.ErrPrice, errPriceOrders)); foreach (var order in errPriceOrders) { //Log4NetUtility.Info("", "存在异常价格存单 Price:" + order.price); #region CancelOrder //CancelOrder cancel = robotTrade.CancelOrder(symbol, order.order_id); //if (cancel.result) //{ // sessionOrders.Remove(order); // order.status = "3"; // //DbHelper.DBSaveChange(doubleorder, "UpDate"); // Log4NetUtility.Info("缓存单验证", "已撤销重复Order。id:" + Utils.ShortID(order.order_id) + " Price:" + order.price); //} //else //{ // string errmsg = ""; // if (cancel.error_code.Contains("3008")) // { // sessionOrders.Remove(order); // //DbHelper.CreateInstance().RemoveOrder(doubleorder); // errmsg = "已清除脏数据Order。id:" + Utils.ShortID(order.order_id) + " Price:" + order.price; // } // else // { // errmsg = "撤销重复Order失败。id:" + Utils.ShortID(doubleorder.order_id) + " msg:" + cancel.error_code + cancel.msg; // } // Log4NetUtility.Info("缓存单验证", errmsg); // //DbHelper.CreateInstance().AddErrInfo("缓存单验证", errmsg); //} #endregion } //CheckSessionDoTime = -1; flag = true; } if (flag) { return; } #endregion #region 调整订单数量 if return int deff = buycount + sellcount - info.buyOrderCount - info.sellOrderCount; #region 多单 return if (deff > 1) { Log4NetUtility.Info("MoreOrder", string.Format("Order数大于初始值,现值:{0} 初始:{1}", buycount + sellcount, info.buyOrderCount + info.sellOrderCount)); Order cancelOrder; if (buycount > sellcount) { cancelOrder = SessionOrders.OrderBy(a => a.price).First(); } else { cancelOrder = SessionOrders.OrderBy(a => a.price).Last(); } SessionEvent?.Invoke(null, new SessionEventArgs(SessionEventType.MoreOrder, new List <Order>() { cancelOrder })); return; } #endregion #region 少单 return if (deff < -1) { Log4NetUtility.Info("LessOrder", string.Format("Order数小于初始值,现值{0} 初始{1}", buycount + sellcount, info.buyOrderCount + info.sellOrderCount)); SessionEvent?.Invoke(null, new SessionEventArgs(SessionEventType.LessOrder)); return; } #endregion #endregion #region 判断补充丢单 if return var lostorder = GetLostOrder(SessionOrders); if (lostorder != null) { SessionEvent?.Invoke(null, new SessionEventArgs(SessionEventType.LostOrder, new List <Order>() { lostorder })); return; } #endregion } } #region catch\finally catch (Exception e) { //DbHelper.CreateInstance().AddErrInfo("缓存验证", e); Log4NetUtility.Error("缓存验证", Utils.Exception2String(e)); DbHelper.CreateInstance().AddError("缓存验证", e); } finally { checkSessionDoTime = -1; checkRunning = false; } #endregion } }