public void Match(SpotOrder so) { if (so == null) { Log.Info("委托对象为空,不能撮合"); return; } switch (so.OrderPolicy) { case OrderPolicy.限价申报: price.Match(so); break; case OrderPolicy.限价FOK: priceOk.Match(so); break; case OrderPolicy.市价剩余转限价: mtp.Match(so); break; case OrderPolicy.市价FOK: marketFok.Match(so); break; case OrderPolicy.市价IOC: marketIoc.Match(so); break; default: Log.Info("交易策略有问题,不能撮合:{0}", so.ToString()); break; } }
public static void SendEmail(this Trader t, string msg) { if (t.ShouldEmail()) { log.Info(string.Format("邮件|{0}:{1}", t.Name, msg)); } }
public Task SendToWait(string to, string subject, string content) { var t = Task.Factory.StartNew(() => { try { MailMessage mm = new MailMessage(); MailAddress Fromma = new MailAddress(FromAddr); MailAddress Toma = new MailAddress(to, null); mm.From = Fromma; //收件人 mm.To.Add(to); //邮箱标题 mm.Subject = subject; mm.IsBodyHtml = true; //邮件内容 mm.Body = content; //内容的编码格式 mm.BodyEncoding = System.Text.Encoding.UTF8; mm.DeliveryNotificationOptions = DeliveryNotificationOptions.OnSuccess; mm.CC.Add(Toma); sc.Send(mm); var truncate = content.Length > 100 ? content.Substring(0, 100) : content; log.Info(string.Format("{0}-{1}-{2}", to, subject, truncate)); } catch (Exception e) { log.Error(e, string.Format("{0}-{1}-{2}", to, subject, content.Length > 100?content.Substring(0, 100):content)); } }); return(t); }
public ContractFuse(Contract c) { this.Contract = c; startTime = null; boundary = new FuseBoundary(c, FuseSpanInMin); boundary.Extrem.OnExtremChanged += extrem_OnExtremChanged; MaxPrice = boundary.CalMaxPrice(); MinPrice = boundary.CalMinPrice(); Excutor = new FuseExcutor( () => { return((decimal)MaxPrice); }, () => { return((decimal)MinPrice); }, (a) => { Log.Info(string.Format("熔断结束无成交,改动最大值,旧{0},新{1}", MaxPrice, a)); MaxPrice = a; }, (a) => { Log.Info(string.Format("熔断结束无成交,改动最小值,旧{0},新{1}", MinPrice, a)); MinPrice = a; }, (a) => { startTime = a; }, () => { var emax = boundary.Extrem.MaxIn5Min; var emin = boundary.Extrem.MinIn5Min; var nmax = boundary.CalMaxPrice(); var nmin = boundary.CalMinPrice(); Log.Info(string.Format("熔断结束有成交,大新{0}-旧{1},小新{2}-旧{3},5分钟最大值{4}-最小值{5}", MaxPrice, nmax, MinPrice, nmin, emax, emin)); MaxPrice = nmax; MinPrice = nmin; } ); }
public bool Pay(string to, decimal amount) { return(Except <bool>(() => { var toUnit = amount * 100000000 - 10000; var url = string.Format(payUrl, WalletId, MainPwd, SecondPwd, to, toUnit); var r = HttpExecutor.Get(url); Log.Info(r); //var ro = JsonConvert.DeserializeObject<TransId>(r); //ro.to = to; ro.amount = amount; ro.when = DateTime.Now; //tc.AddPayment(ro); return true; })); }
/// <summary> /// 还钱:系统亏损分担,应计入日志 /// </summary> /// <param name="d"></param> /// <param name="t"></param> /// <returns></returns> public bool Repay(decimal d, Trader t) { var r = AddPublic(d); if (!r) { return(false); } var cur = t.Account.BailAccount.Total; if (OnSystemAccountChanged != null) { Log.Info(string.Format("系统还款:{0}-金额{1}-系统金额{2}-用户还款前金额{3}-线程{4}", t.Name, d, PublicSum, t.Account.BailAccount.Sum, Thread.CurrentThread.ManagedThreadId)); OnSystemAccountChanged(d, t, null, PublicSum, PrivateSum, SysAccountChangeType.还款, cur); } return(true); }
void Check() { if (container == null || Handle == null || container.Orders == null || container.Orders.Count == 0) { return; } var list = container.Orders.Values.ToList(); foreach (var v in list) { if (v == null || v.SellQueue == null || v.SellQueue.Count == 0 || v.BuyQueue == null || v.BuyQueue.Count == 0) { continue; } var s = v.Sell1Price; var b = v.Buy1Price; if (s > b) { continue; } var s1 = v.SellQueue.OrderBy(a => a.Price).FirstOrDefault(); if (s1 == null) { continue; } log.Info(string.Format("出现买1价大于卖1价-{0}-卖1价{1}-买1价{2}", s1.Contract.Code, s, b)); Handle(s1); } }
void SaveSnap() { StringBuilder sb = new StringBuilder(); sb.Append("分摊前每用户钱数:"); var ts = traders.ToList(); foreach (var v in ts) { sb.AppendFormat("{0}-{1},", v.Name, v.Account.BailAccount.Total); v.SetBailTotalSnap(v.Account.BailAccount.Total); } SystemAccount.Instance.SetPreTotal(SystemAccount.Instance.PublicSum); sb.AppendFormat("总亏损:{0}", SystemAccount.Instance.PublicSum); log.Info(sb.ToString()); }
public override void Save(object o) { var oo = o as Order; log.Info(oo.ToShortString()); base.Save(o); }
void monitorTimer_Elapsed(object sender, ElapsedEventArgs e) { try { monitorTimer.Stop(); var tl = GetTraderExceptRobot(); foreach (var v in tl) { var ratio = v.GetMaintainRatio(); var shouldMonitor = ratio < SysPrm.Instance.MonitorParams.AlarmMaintainRatio; var isMonitoring = v.IsMonitoring(); if (shouldMonitor) { if (!isMonitoring) { log.Info(string.Format("开始监视:人{0}-率{1}-爆{2}-线程{3}", v.Name, ratio, v.IsBlasting(), Thread.CurrentThread.ManagedThreadId)); Monitor(v); } } else { if (isMonitoring) { //log.Info(string.Format("",v.Name,ratio)) log.Info(string.Format("结束监视:人{0}-率{1}-爆{2}-线程{3}", //"爆仓检查定时器:人{0}-监视信号{1}-爆仓信号{2}-线程{3}", v.Name, ratio, v.IsBlasting(), Thread.CurrentThread.ManagedThreadId)); Clear(v); } } } } catch (Exception ex) { log.Error(ex); } finally { monitorTimer.Start(); } }
/// <summary> /// 卖:只能卖有的,且一个只能卖一次 /// 买无限制 /// </summary> /// <param name="so"></param> /// <returns></returns> bool CheckCount(SpotOrder so) { if (so.Direction == TradeDirectType.卖) { var cc = so.Trader.Account.CacheAccount.BtcAccount.Sum;//.GetCoinAcount(so.Coin).Balance;(可用的) log.Info(string.Format("实际:{0},我卖:{1}", cc, so.Count)); if (cc < so.Count) { return(false); } var soc = so.Trader.GetSpotOrders(); decimal ocs = 0; log.Info(string.Format("soc的结果:{0}", soc)); log.Info(string.Format("比特币的可用资金:{0}", cc)); if (soc != null) { //注:卖出去的马上就会被冻结(相当于不是我的),为什么还要用可用的减去卖出去的BTC(相当于要扣除了一次BTC) ocs = soc.Where(a => a.Coin == so.Coin && a.Direction == TradeDirectType.卖 && a.State == OrderState.等待中 || a.State == OrderState.部分成交).Select(a => a.Count).Sum(); //var kk = soc.Where(a => a.Coin == so.Coin && a.Direction == TradeDirectType.卖).ToList(); // log.Info(string.Format("soc里面SUM:{0}///{1}", ocs,kk.Count())); // foreach (var item in kk) // { // log.Info(string.Format("数据:{0},{1},{2},{3}", item.Id, item.Direction, item.State,kk.Count())); // } // var r = cc - ocs - so.Count; var r = cc - so.Count; //log.Info(string.Format("soc里面计算:{0}={1} - {2}-{3}", r, cc,ocs , so.Count)); if (r >= 0) { return(true); } else { return(false); } } return(true); } return(true); }
public static decimal TransBonus(Trader t, List <string> invitedNames) { if (t == null || invitedNames == null || invitedNames.Count == 0) { return(0); } decimal result = 0; foreach (var v in invitedNames) { if (string.IsNullOrEmpty(v)) { continue; } bool r = TraderService.OperateInvitorBonus(t, InvitorBonusInCny, "被推荐人" + v); result += InvitorBonusInCny; log.Info(string.Format("{0}成功推荐了{1},获取奖金{2}元", t.Name, v, InvitorBonusInCny)); } return(result); }
/// <summary> /// 计算平仓比率:需要平仓的份数 /// 每份合约得到的资金数=释放的维持保证金-买入价格 /// </summary> /// <param name="up"></param> /// <returns></returns> decimal CalRatio(Trader t, PositionSummary up, decimal needed) { try { if (up == null) { Log.Info(string.Format("计算比例时合约为空:仓{0}-人{1}", up.CName, t.Name)); return(0); } var cp = Market.Get(up.CName).NewestDealPrice; var pp = up.GetReleasePerPos((a) => { return(model.Contracts.Where(c => c.Code == a).FirstOrDefault()); }, cp); var r = needed / pp; Log.Info(string.Format("平仓份数:{0}-{1}-价{2}-释{3}-份{4}", t.Name, up.CName, cp, pp, r)); return(r); } catch (Exception ex) { Log.Error(ex); return(0); } }
public void Send(List <string> mobiles, string content, string corpid = "1", string proId = "1012818") { try { if (mobiles == null || mobiles.Count == 0 || string.IsNullOrEmpty(content)) { return; } //sname:提交用户 //spwd:提交密码 //scorpid:企业代码 //sprdid:产品编号 //sdst:接收号码,多个以','分割,不可超过100000个号码 //smsg:短信内容 ///submitdata/service.asmx/g_Submit?sname=string&spwd=string&scorpid=string&sprdid=string&sdst=string&smsg=string /// StringBuilder sb = new StringBuilder(); sb.Append(url); sb.AppendFormat("/g_Submit?sname={0}&spwd={1}&scorpid={2}&sprdid={3}", name, pwd, corpid, proId); StringBuilder sb2 = new StringBuilder(); foreach (var v in mobiles) { sb2.AppendFormat("{0},", v); } if (sb2.Length > 0) { sb2.Remove(sb2.Length - 1, 1); } sb.AppendFormat("&sdst={0}&smsg={1}", sb2.ToString(), content); var Url = sb.ToString(); // CookieContainer cc = new CookieContainer(); System.Net.HttpWebRequest wReq = (HttpWebRequest)System.Net.WebRequest.Create(Url); //wReq.CookieContainer = cc; // Get the response instance. System.Net.WebResponse wResp = wReq.GetResponse(); System.IO.Stream respStream = wResp.GetResponseStream(); string r = ""; using (System.IO.StreamReader reader = new System.IO.StreamReader(respStream, Encoding.UTF8)) { r = reader.ReadToEnd(); } log.Info(string.Format("{0}-{1}", sb.ToString(), r)); } catch (Exception e) { log.Error(e); } }
/// <summary> /// 下单后,冻结维持保证金或需要的金额 /// 同时要添加到用户的下单列表 /// 下单列表只保留最近的10000单 /// </summary> /// <param name="o"></param> public bool Handle(Order o) { try { log.Info(string.Format("下单后==下单订单信息:{0}", o)); if (o.IsMarketPrice()) { o.Price = 0; } bool bailresult = true; //如果是市价,则不冻结也不解冻 if (!o.IsMarketPrice() && o.IsNeedBailExceptMaintainBail()) { var c = o.GetSellOpenCountToFreeze(); bailresult = TraderService.OperateAccount(o.Trader, c, AccountChangeType.保证金冻结, "system", o); log.Info(string.Format("下单后==保证金冻结成功,冻结{0}", o.GetNeededCache())); } if (bailresult) { o.State = OrderState.等待中; o.Trader.Orders().Add(o); //成功下单,重新计算保证率 o.Trader.RaiseRatioChangedAfterOrder(); log.Info(string.Format("下单后==已将{0}添加到用户的下单列表", o)); } return(bailresult); } catch (Exception e) { Singleton <TextLog> .Instance.Error(e, "order post handle"); return(false); } }
void Check(List <T> l, object loc) { if (l.Count == 0) { return; } var tl1 = l.ToList(); if (tl1.Count == 0) { return; } List <T> tl = new List <T>(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < tl1.Count; i++) { var v = tl1[i]; if (!IsExpired(v)) { continue; } tl.Add(v); sb.AppendFormat("-编号{0}-方向{1}-数量{2}-时间{3}-价格{4}-合约{5}", v.Id, v.Direction, v.OrderCount, v.OrderTime, v.Price, v.Sign); } if (sb.Length > 0) { sb.Insert(0, Tag); sb.Insert(0, "因为超期抛弃委托"); log.Info(sb.ToString()); } if (tl.Count > 0) { lock (loc) { foreach (var v in tl) { l.Remove(v); } } if (OnExpired != null) { OnExpired(tl); } } }
void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { try { t.Stop(); Execute(); } catch (Exception ex) { log.Error(ex); } finally { log.Info(thisLog.ToString()); t.Start(); } }
public bool Redo(Order o) { lock (redoSync) { if (o == null) { return(false); } //如果不是等待中或部分成交,则已经处理完毕,不需要撤销 if (!o.IsArrangable()) { return(false); } //如果正在撮合,不能撤销 if (o.IsArranging()) { return(false); } //撤销同时设置状态 var r = Container.Remove(o); bool success = false; if (r) { //Unfreeze(o); success = true; } o.Trader.Orders().Remove(o); //有可能已经成交,那就不能再引发完成事件,会倒持重复存储 if (o.State != OrderState.已撤销 && o.State != OrderState.已成交 && o.State != OrderState.已行权) { o.State = OrderState.已撤销; o.Unfreeze(); RaiseOnFinish(o); } else { log.Info(string.Format("重复撤销{0}", o.ToString())); } return(success); } }
public virtual void EatOrder(Order o) { if (o.Direction == TradeDirectType.卖) return; if (o.Trader.Id == this.TraderId) return; if (o.State != OrderState.等待中 && o.State != OrderState.部分成交) return; if (!ShouldEat(o)) return; var oid = NewId(); var r = OrderItFunc(this.TraderId, o.Contract.Id, TradeDirectType.卖 , OrderType.开仓, OrderPolicy.市价FOK, o.Count, o.Price, oid.ToString() ); var ls = string.Format("用户:{0},序号:{1},对手单:{2},本单:{3}", TraderId, oid, o.ToShortString(), r.ToString()); log.Info(ls); }
public void Sell(Trader t, PositionSummary up, int count, int blastId) { int total = count; t.SetSell(up, true); int loopcount = 0; while (total > 0) { //检查持仓 var pos = t.GetPositionSummary(up.CCode, PositionType.权利仓); if (pos == null) { break; } lock (pos.PositionType) { if (pos.PositionType != this.positionType.ToString()) { break; } var closable = t.GetClosableCount(pos); if (closable <= 0) { break; } if (loopcount++ > MaxLoopCount) { Log.Info(string.Format("平仓循环超过{0}次,结束:{1}3-2平仓操作:{2}-仓{3}-平数{4}", MaxLoopCount, up.CName, this.positionType, up, count)); break; } var cs = CreateSellOrder(t, up, total); matcher.Handle(cs.Item1); Log.Info(string.Format("{0}平仓操作:{1}-仓{2}-平数{3}-熔{4}-单{5}", up.CName, this.positionType, up.CName, count, cs.Item2, cs.Item1.ToShortString())); BlasterOperaton bo; bo = new BlasterOperaton { Id = IdService <BlasterOperaton> .Instance.NewId(), BlasterRecordId = blastId, OpOrderId = cs.Item1.Id, Order = cs.Item1, PositionId = 0, Result = cs.Item1.State == OrderState.已成交 }; RaiseSell(bo); if (t.GetMaintainRatio() >= 1) { return; //当保证率大于等于1时平仓结束 } if (cs.Item2) { return; } else { total -= cs.Item1.TotalDoneCount; } } } t.SetSell(up, false); }
/// <summary> /// 手动行权 /// </summary> /// <param name="contractId"></param> /// <param name="basePrice"></param> public void ManualExcute(int contractId, decimal basePrice, Market m, string name) { log.Info(string.Format("开始手动行权:{0}-{1}", contractId, basePrice)); List <int> l = new List <int>(); var oss = OptionService.Model.Traders.Where(a => a.Orders().Count > 0).ToList(); //先撤单 foreach (var s in oss) { var aa = s.Orders().GetLivesByContractId(contractId); foreach (var b in aa) { OptionService.Matcher.Redo(b); l.Add(b.Id); } } var traders = ts.ToList(); //遍历所有交易员 for (int i = 0; i < traders.Count; i++) { var upl = traders[i].GetPositionSummaries().Where(a => a.Contract.Id == contractId); var has = upl != null && upl.Count() > 0; log.Info(string.Format("{0}-{1}-{2}-{3}个-应{4}", traders[i].Name, has ? upl.First().PositionType : "", has ? upl.First().Contract.Id : 0, has ? upl.First().Count : 0, contractId)); if (upl == null) { continue; } var uppp = upl.ToList(); //再遍历他的当前合约的持仓汇总 for (int j = 0; j < upl.Count(); j++) { Execute(uppp[j], traders[i], basePrice, true); var q = traders[i].GetPositionSummaries().Where(a => a.Contract.Id == contractId).FirstOrDefault(); if (q == null) { continue; } var v = q; traders[i].RemovePositionSummary(v.CCode);//根据合约代码移除持仓汇总 var pd = new PositionSummaryData { OrderType = v.OrderType, Commission = 0, TotalValue = v.TotalValue, Maintain = 0, ClosableCount = traders[i].GetClosableCount(v), FloatProfit = v.FloatProfit, BuyTotal = v.BuyTotal, BuyPrice = v.BuyPrice, Count = v.Count, PositionType = v.PositionType, ContractId = v.Contract.Id, CloseProfit = v.CloseProfit, TraderId = traders[i].Id, When = DateTime.Now }; pds.Save(pd); OnRemovedByExe(traders[i], v); var uq = traders[i].Positions.Where(a => a.Order.Contract.Id == contractId); if (uq == null) { continue; } var uql = uq.ToList(); foreach (var u in uql) { traders[i].Positions.Remove(u); } } } m.Board.Remove(name); handler.UpdateOrderStateToExecuted(l); if (OnContractExecuted != null) { OnContractExecuted(contractId, basePrice); } log.Info(string.Format("结束手动行权:{0}-{1}", contractId, basePrice)); }
public OrderResult AddOrder(int who, int contract, TradeDirectType dir, OrderType orderType, OrderPolicy policy, int count, decimal price, string userOpId = "") { if (IsStoped) { return new OrderResult { ResultCode = 330, Desc = "系统维护中,请稍后重试" } } ; var o = Model.CreateOrder(who, contract, dir, orderType, policy, count, price); if (o == null) { return new OrderResult { ResultCode = 10, Desc = "不能创建委托,请检查参数", UserOpId = userOpId } } ; o.State = OrderState.等待中; if (!IsAcceptByFuse(o)) { return(new OrderResult { UserOpId = userOpId, Desc = "价格不能超出熔断范围", Order = o, ResultCode = 401 }); } var r = preHandler.CouldOrder(o); if (r.ResultCode == 10) { log.Info(string.Format("异常:人{0}-约{1}-向{2}-开{3}-策{4}-量{5}-价{6}-{7}", who, contract, dir, orderType, policy, count, price, userOpId)); return(new OrderResult { UserOpId = userOpId, Desc = "下单未知错误", Order = o, ResultCode = 401 }); } log.Info(string.Format("下单前检查=={0}=={1}", o, r)); if (r.IsSuccess) { var br = postHandler.Handle(o); if (!br) { return(new OrderResult { UserOpId = userOpId, Desc = "保证金不足", Order = o, ResultCode = 5 }); } log.Info(string.Format("下单后处理=={0}=={1}", o, r)); Matcher.Handle(o); log.Info(string.Format("撮合后=={0}=={1}", o, r)); } return(new OrderResult { UserOpId = userOpId, Desc = r.Desc, Order = o, ResultCode = r.ResultCode }); }
/// <summary> /// 爆仓 /// </summary> /// <param name="t">要爆仓的用户</param> /// <returns>true表示保证率满足要求,false表示保证率不满足要求</returns> public bool Blast(Trader t) { //Id小于1的用户是系统机器人 if (t.Id < 1) { return(true); } var mr = t.GetMaintainRatio(Market); if (mr >= threshold) { return(true); } var br = CreateRecord(t, mr, true); if (OnBlasting != null) { if (t.ShouldMsg()) { OnBlasting(br); } } var ps = t.GetPositionSummaries(); //所有持仓都平了:虽然不一定成交 if (ps == null || ps.Count() == 0) { return(false); } var bail = t.GetMaintain(Market); var needed = bail * SysPrm.Instance.MonitorParams.BlastOnceRatio; // / 10m; if (needed < 500m) { needed = 500m; } foreach (var up in ps) { if (up == null || up.Count == 0) { continue; } if (t.IsSelling(up)) { continue; } var buyRatio = CalRatio(t, up, needed); if (buyRatio == 0m) { continue; } Log.Info(string.Format("{0}爆仓开始:{1}-{2}-仓{3}-平仓份数{4}-需{5}", this.positionType, t.Name, mr, up.CCode, buyRatio, needed)); var count = (int)Math.Ceiling(buyRatio); var closableCount = t.GetClosableCount(up.CCode, this.positionType == PositionType.权利仓 ? TradeDirectType.卖 : TradeDirectType.买); if (count > closableCount) { count = closableCount; } sellor.Sell(t, up, count, br.Id); if (t.GetMaintainRatio(Market) >= threshold) { break; } } var br1 = CreateRecord(t, mr, false); if (OnBlasted != null) { OnBlasted(br1); } if (t.GetMaintainRatio() >= 1) { return(true); } return(false); }
/// <summary> /// 匹配的数量处理 /// 返回最后成交价格用于交易策略处理 /// </summary> /// <param name="r"></param> /// <param name="o"></param> /// <returns>最后的成交价格</returns> protected virtual decimal HandleCount(IEnumerable <Order> source, Order o) { if (source == null || source.Count() == 0) { return(-1); } var r = source.ToList(); decimal p = -1; foreach (var v in r) { //如果不是可成交状态,忽略 if (!v.IsArrangable()) { continue; } if (v.IsArranging()) { continue; } var fu = Market.Get(o.Contract.Name).fuser; var fur = fu.ShouldAllowDeal(v.Price); if (fur != 0) { HandleFuse(o, v, fur == 1?fu.MaxPrice ?? 0:fu.MinPrice ?? 0); log.Info(string.Format("因超出价格范围不能成交:成交价{0},最高价{1},最低价{2},主{0},从{1}", v.Price, fu.MaxPrice ?? 0, fu.MinPrice ?? 0, o.ToShortString(), v.ToShortString())); //o.Detail = "因超出价格范围不能成交,此委托将被撤销"; Redo(o); if (o.State == OrderState.已撤销) { break; } else { continue; } } if (v.Count == o.Count) { var cm = CouldMatchByBail(o, v); if (cm == 0) { v.BeginArrange(); SaveDeal(o, v, v.Price); Matched(v, v.Trader != o.Trader); Matched(o, v.Trader != o.Trader); v.EndArrange(); return(v.Price);; } else if (cm == 1) { break; } else if (cm == 2) { continue; } } else if (v.Count > o.Count) { var cm = CouldMatchByBail(o, v); if (cm == 0) { v.BeginArrange(); SaveDeal(o, v, v.Price); Matched(o, v.Trader != o.Trader); lock (v) { v.Count -= o.Count; } PartialMatchedTrue(v, o.Count, v.Trader != o.Trader); v.EndArrange(); return(v.Price); } else if (cm == 1) { break; } else if (cm == 2) { continue; } } else { var cm = CouldMatchByBail(o, v); if (cm == 0) { v.BeginArrange(); SaveDeal(o, v, v.Price); Matched(v, v.Trader != o.Trader); lock (o) { o.Count -= v.Count; } PartialMatchedTrue(o, v.Count, v.Trader != o.Trader); p = v.Price; v.EndArrange(); } else if (cm == 1) { break; } else if (cm == 2) { continue; } } } return(p); }