private void UpdateTable() { try { var acc = AccountStatus.Instance.AccountData; if (acc == null) { return; } var orders = MarketOrdersStorage.Instance.MarketOrders ?? new List <MarketOrder>(); var sumPos = PositionSummary.GetPositionSummary(orders, acc.Currency, (float)acc.Balance) ?? new List <PositionSummary>(); Invoke(new Action <List <PositionSummary> >(lst => grid.DataBind(lst)), sumPos); var height = sumPos.Count * grid.CellHeight + grid.CaptionHeight + 2; if (grid.Width < grid.MinimumTableWidth) // учесть высоту скролбара { height += SystemInformation.HorizontalScrollBarHeight; } if (height != lastHeight) { lastHeight = height; ContentHeightChanged(height); } } catch (Exception ex) { Logger.Error("UpdateAccountInfo error", ex); } }
public void CreateTest3() { UserPosition up = createPosition(10, 90, OrderType.开仓, TradeDirectType.卖); var ps = new PositionSummary(up, 90m); var up1 = createPosition(20, 120, OrderType.开仓, TradeDirectType.卖); ps.Update(up1, true, 120); var up2 = createPosition(5, 200, OrderType.平仓, TradeDirectType.买); ps.Update(up2, false, 200); Assert.AreEqual(25, ps.Count); // Assert.AreEqual(25, ps.ClosableCount); Assert.AreEqual(110, ps.BuyPrice); Assert.AreEqual(2750, ps.BuyTotal); Assert.AreEqual(-2250, ps.FloatProfit); Assert.AreEqual(-450, ps.CloseProfit); Assert.AreEqual(-5000, ps.TotalValue); }
public void CreateTest5() { UserPosition up = createPosition(10, 90, OrderType.开仓, TradeDirectType.卖); var ps = new PositionSummary(up, 90m); var up1 = createPosition(20, 120, OrderType.开仓, TradeDirectType.卖); ps.Update(up1, true, 120); var up2 = createPosition(5, 200, OrderType.平仓, TradeDirectType.买); ps.Update(up2, false, 200); var up3 = createPosition(10, 200, OrderType.开仓, TradeDirectType.卖); ps.Update(up3, true, 200); var up4 = createPosition(15, 140, OrderType.平仓, TradeDirectType.买); ps.Update(up4, false, 140); Assert.AreEqual(20, ps.Count); // Assert.AreEqual(20, ps.ClosableCount); Assert.IsTrue(135.714m - ps.BuyPrice < 0.001m); Assert.IsTrue(2714.28m - ps.BuyTotal < 0.01m); Assert.IsTrue(-85.72m - ps.FloatProfit < 0.01m); Assert.IsTrue(-514.29m - ps.CloseProfit < 0.01m); Assert.AreEqual(-2800, ps.TotalValue); }
/// <summary> /// 生成买平操作的委托 /// </summary> /// <param name="up"></param> /// <param name="total"></param> /// <returns></returns> protected override Tuple <Order, bool> CreateSellOrder(Trader t, PositionSummary up, int total) { decimal price; var fuse = GetFuser(up); var pm = GetPossibleMatch(up) .Where(a => a.Price <(decimal)fuse.MaxPrice && a.Price>(decimal) fuse.MinPrice) .OrderBy(a => a.Price) .FirstOrDefault(); if (pm == null) { price = (decimal)fuse.MaxPrice; var closableCount = t.GetClosableCount(up.CCode, TradeDirectType.买); var r = new Order { Id = IdService <Order> .Instance.NewId(), OrderPolicy = OrderPolicy.限价申报, Price = price, Count = closableCount, ReportCount = closableCount, Contract = up.GetContract(this.model), Direction = TradeDirectType.买, OrderType = OrderType.平仓, OrderTime = DateTime.Now, Trader = t, State = OrderState.等待中, IsBySystem = true }; PutInReorder(r, fuse, true, up); return(Tuple.Create(r, true)); } else { price = pm.Price; //下单数量是1数量和平仓数量的较小值 var pcount = pm.Count >= total?total:pm.Count; if (pcount > SysPrm.Instance.MonitorParams.MaxCountPerSell) { pcount = SysPrm.Instance.MonitorParams.MaxCountPerSell; } var r = new Order { Id = IdService <Order> .Instance.NewId(), OrderPolicy = OrderPolicy.市价IOC, Price = price, Count = pcount, ReportCount = pcount, Contract = up.GetContract(this.model), Direction = TradeDirectType.买, OrderType = OrderType.平仓, OrderTime = DateTime.Now, Trader = t, State = OrderState.等待中, IsBySystem = true }; return(Tuple.Create(r, false)); } }
public ReorderItem(Order up, ContractFuse cf, bool isHandelMax, PositionSummary pos, IMatch matcher) { this.matcher = matcher; Blaster.Log.Info(string.Format("平仓委托重新报价加入队列:{0}-大{1}-边{2},{3}-单{4}", up.Trader.Name, isHandelMax, cf.MaxPrice, cf.MinPrice, up.ToShortString())); this.order = up; this.cf = cf; this.Pos = pos; HisOrderIds = new List <int> { up.Id }; this.isHandleMax = isHandelMax; //引发熔断-- cf.ShouldAccept(up); if (isHandelMax) { cf.OnMaxChanged += cf_OnMaxChanged; } else { cf.OnMinChanged += cf_OnMinChanged; } cf.Excutor.OnFuseOver += Excutor_OnFuseOver; CreateTime = DateTime.Now; checkTimer = new Timer(); checkTimer.Interval = ContractFuse.FuseSpanInMin / 2 * 60 * 1000; checkTimer.Elapsed += checkTimer_Elapsed; checkTimer.Start(); }
public void Add(Order up, ContractFuse cf, bool isHandelMax, PositionSummary ps) { var feh = new ReorderItem(up, cf, isHandelMax, ps, this.matcher); feh.OnDone += feh_OnDone; list.Add(feh); }
private void CalculateCurrentLeverage() { if (!AccountStatus.Instance.isAuthorized) { return; } try { var orders = MarketOrdersStorage.Instance.MarketOrders; if (orders == null || orders.Count == 0) { return; } var account = AccountStatus.Instance.AccountData; if (account == null) { return; } var lstPos = PositionSummary.GetPositionSummary(orders, account.Currency, (float)account.Balance); currentLeverage = lstPos.Count == 0 ? 0 : lstPos.First(p => string.IsNullOrEmpty(p.Symbol)).Leverage; tbCurLeverage.Text = currentLeverage.ToString("f3"); } catch (Exception ex) { Logger.Error("Ошибка в CalculateCurrentLeverage()", ex); } }
private bool CheckMargin(string symbol, int side, int volume) { var minLeverageToWarn = UserSettings.Instance.MessageOnEnterExceedLeverage ? UserSettings.Instance.RiskLeverCritical : 10000; var equity = AccountStatus.Instance.AccountData.Equity; if (equity == 0) { return(false); } if (minLeverageToWarn == 0) { return(true); } var orders = MarketOrdersStorage.Instance.MarketOrders; if (orders == null || orders.Count == 0) { return(true); } var depoCurx = AccountStatus.Instance.AccountData.Currency; // подсчет плеча var quotes = QuoteStorage.Instance.ReceiveAllData(); var posSum = PositionSummary.GetPositionSummary(quotes, orders, depoCurx); var leverage = posSum.Sum(p => !string.IsNullOrEmpty(p.Symbol) ? p.Leverage : 0); var volumeBySymbol = posSum.Sum(p => p.Symbol == symbol ? p.Volume : 0); var newVolumeBySymbol = volumeBySymbol + (side * volume); var newVolumeDepo = ConvertBaseVolumeToDepo(newVolumeBySymbol, symbol, depoCurx, quotes); var newSymbolLeverage = Math.Abs(newVolumeDepo / (float)equity); var oldSymbolLeverage = posSum.Sum(p => p.Symbol == symbol ? p.Leverage : 0); if (newSymbolLeverage <= oldSymbolLeverage) { return(true); // экспозиция не увеличивается } var newLeverage = leverage - oldSymbolLeverage + newSymbolLeverage; if (newLeverage >= minLeverageToWarn) { var msg = string.Format(Localizer.GetString("MessageWarningExceedLeverageFmt"), leverage, newLeverage, minLeverageToWarn); if (MessageBox.Show(msg, Localizer.GetString("TitleWarning"), MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.No) { return(false); } } return(true); }
public async Task <ActionResult> Create(PositionDto positionDto) { if (string.IsNullOrEmpty(positionDto.Description)) { return(StatusCode(StatusCodes.Status422UnprocessableEntity)); } var position = new Position(positionDto.Description); await positionRepository.InsertAsync(position); return(CreatedAtAction( nameof(Get), new { id = position.Id.ToString() }, PositionSummary.FromDomain(position))); }
public void CreateTest() { UserPosition up = createPosition(10, 90, OrderType.开仓, TradeDirectType.卖); var ps = new PositionSummary(up, 90m); Assert.AreEqual(10, ps.Count); // Assert.AreEqual(10, ps.ClosableCount); Assert.AreEqual(90, ps.BuyPrice); Assert.AreEqual(900, ps.BuyTotal); Assert.AreEqual(0, ps.FloatProfit); Assert.AreEqual(0, ps.CloseProfit); Assert.AreEqual(-900, ps.TotalValue); }
public static decimal GetReleasePerPos(this PositionSummary up, Func <string, Contract> GetContractByCode, decimal curPrice) { if (up.PositionType == "义务仓") { var c = GetContractByCode(up.CCode); if (c == null) { return(0); } var one = c.GetMaintainForContract(curPrice); var delta = one - curPrice; return(delta); } else { return(curPrice); } }
public void Calc(UserPosition up, bool isAdd, decimal curPrice) { var k = up.Order.Contract.Code; PositionSummary ps = null; lock (calcSync) { if (!dic.ContainsKey(k)) { ps = new PositionSummary(up, curPrice); dic.Add(k, ps); } else { ps = dic[k]; dic[k].Update(up, isAdd, curPrice); } } }
public void CreateTest2() { UserPosition up = createPosition(10, 90, OrderType.开仓, TradeDirectType.卖); var ps = new PositionSummary(up, 90m); var up1 = createPosition(20, 120, OrderType.开仓, TradeDirectType.卖); ps.Update(up1, true, 120); Assert.AreEqual(30, ps.Count); // Assert.AreEqual(30, ps.ClosableCount); Assert.AreEqual(110, ps.BuyPrice); Assert.AreEqual(3300, ps.BuyTotal); Assert.AreEqual(-300, ps.FloatProfit); Assert.AreEqual(0, ps.CloseProfit); Assert.AreEqual(-3600, ps.TotalValue); }
/// <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 PositionSummaryDto(PositionSummary ps, decimal curPrice, int closableCount) { this.Id = ps.Id; this.OrderType = ps.OrderType; this.PositionType = ps.PositionType; this.BuyPrice = Math.Round(ps.BuyPrice, 2); this.BuyTotal = Math.Round(ps.BuyTotal, 2); this.Contract = new ContractDto(ps.Contract); this.Count = ps.Count; this.ClosableCount = closableCount > 0 ? closableCount : 0; this.TotalValue = Math.Round(ps.TotalValue, 2); this.FloatProfit = Math.Round(ps.FloatProfit, 2); this.CloseProfit = Math.Round(ps.CloseProfit, 2); this.Maintain = Math.Round(ps.GetMaintain(curPrice), 2); this.Commission = 0; }
public void RaisePC(PositionSummary p, Trader t) { try { if (p == null) { return; } var m = this.market.Get(p.CName); var np = m == null ? 0m : m.NewestDealPrice; var c = t.GetClosableCount(p); var pd = new PositionSummaryDto(p, np, c); if (OnPositionSummaryChanged != null) { OnPositionSummaryChanged.BeginInvoke(t.Name, pd, null, null); } } catch (Exception ex) { Singleton <TextLog> .Instance.Error(ex, "raisepc"); } }
private void RenderBody(StringBuilder sb) { // заголовок (доход по счету такому-то...) RenderAccountTitle(sb, " "); // таблица статистики по счету RenderStatTableHeader(sb, " "); RenderStatTable(sb, " "); RenderStatTableFooter(sb, " "); // график средств / баланса RenderProfitChart(sb, " "); // таблица - суммарные позы if (openedOrders.Count > 0) { var quotes = QuoteStorage.Instance.ReceiveAllData(); var listSum = PositionSummary.GetPositionSummary(quotes, openedOrders, account.Currency); RenderSummaryOpenDealsTableHeader(sb, " "); RenderSummaryOpenDealsTable(sb, " ", listSum); RenderSummaryOpenDealsTableFooter(sb, " "); // таблица открытых сделок RenderOpenDealsTableHeader(sb, " "); RenderOpenDealsTable(sb, " "); RenderOpenDealsTableFooter(sb, " "); } if (renderClosedDeals) { RenderClosedDealsTableHeader(sb, " "); RenderClosedDealsTable(sb, " "); RenderClosedDealsTableFooter(sb, " "); } }
public static int GetClosableCount(this Trader t, PositionSummary ps) { return(t.GetClosableCount(ps.CCode, ps.PositionType == "权利仓" ? TradeDirectType.卖 : TradeDirectType.买)); }
/// <summary> /// 确认持仓 /// </summary> /// <param name="p1"></param> /// <param name="count"></param> /// <param name="buyPrice"></param> /// <param name="maintain"></param> void vp_c_bp_m(PositionSummary p1, int count, decimal buyPrice, decimal maintain) { Assert.AreEqual(p1.Count, count); Assert.AreEqual(p1.BuyPrice, buyPrice); //Assert.AreEqual(p1.Maintain, maintain); }
/// <summary> /// 将委托放入重新报价队列 /// </summary> /// <param name="o"></param> /// <param name="cf"></param> /// <param name="isFuseMax">是否是上边界发生变化时重新报价</param> protected void PutInReorder(Order o, ContractFuse cf, bool isFuseMax, PositionSummary pos)// upId) { this.fehc.Add(o, cf, isFuseMax, pos); }
protected ContractFuse GetFuser(PositionSummary up) { var f = Market.Get(up.CName); return(f.fuser); }
/// <summary> /// 创建委托 /// </summary> /// <param name="up"></param> /// <param name="total"></param> /// <returns>委托,是否是以熔断价报出</returns> protected abstract Tuple <Order, bool> CreateSellOrder(Trader t, PositionSummary up, int total);
public static bool IsSelling(this Trader t, PositionSummary p) { var k = MakeKey(t, p); return(sellDic.Get(k)); }
//行权 void Execute(PositionSummary up, Trader ts, decimal exeBasePrice, bool isManual = false) { up.Contract.IsNotInUse = true; //if (up.Order == null) return; if (!isManual) { if (up.Contract.ExcuteTime.Date != DateTime.Now.Date) { return; } } if (up.Contract.OptionType == OptionType.认购期权) //认购期权:跌了不行权 { if (exeBasePrice > up.Contract.ExcutePrice) //涨了 { var d = exeBasePrice - up.Contract.ExcutePrice; var t = d * up.Count * up.Contract.CoinCount; if (up.PositionType == "权利仓") //权利方 { ts.Account.BailAccount.Collect(t); //收钱 handler.SaveRecord(ts, up.Contract, PositionType.权利仓, up.Count, exeBasePrice, true, t); TraderService.OperateAccount(ts, t, AccountChangeType.行权划入, "系统操作", null, ts.Account.BailAccount.Total); } else//义务方 { ts.BailPay(t, ts.GetMarket(), null, AccountChangeType.行权划出); handler.SaveRecord(ts, up.Contract, PositionType.义务仓, up.Count, exeBasePrice, false, t); } } else { if (up.PositionType == "权利仓")//权利方 { handler.SaveRecord(ts, up.Contract, PositionType.权利仓, up.Count, exeBasePrice, true, 0); } else//义务方 { handler.SaveRecord(ts, up.Contract, PositionType.义务仓, up.Count, exeBasePrice, false, 0); } } } else//认沽期权:涨了不行权 { if (exeBasePrice < up.Contract.ExcutePrice)//跌了 { var d = up.Contract.ExcutePrice - exeBasePrice; var t = d * up.Count * up.Contract.CoinCount; if (up.PositionType == "权利仓") //权利方 { ts.Account.BailAccount.Collect(t); //收钱 handler.SaveRecord(ts, up.Contract, PositionType.权利仓, up.Count, exeBasePrice, true, t); TraderService.OperateAccount(ts, t, AccountChangeType.行权划入, "系统操作", null, ts.Account.BailAccount.Total); } else//义务方 { ts.BailPay(t, ts.GetMarket(), null, AccountChangeType.行权划出); handler.SaveRecord(ts, up.Contract, PositionType.义务仓, up.Count, exeBasePrice, false, t); } } else { if (up.PositionType == "权利仓")//权利方 { handler.SaveRecord(ts, up.Contract, PositionType.权利仓, up.Count, exeBasePrice, true, 0); } else//义务方 { handler.SaveRecord(ts, up.Contract, PositionType.义务仓, up.Count, exeBasePrice, false, 0); } } } }
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="up"></param> /// <returns></returns> protected override IEnumerable <Order> GetPossibleMatch(PositionSummary up) { return(matcher.Container.GetByDir(up.CCode, TradeDirectType.买)); }
static string MakeKey(Trader t, PositionSummary p) { return(string.Format("{0}-{1}", t.Id, p.CCode)); }
public async Task <IEnumerable <PositionSummary> > Get() { var positions = await positionRepository.GetAsync(); return(positions.Select(domain => PositionSummary.FromDomain(domain))); }
/// <summary> /// 平仓操作的交易对象 /// </summary> /// <param name="up"></param> /// <returns></returns> protected abstract IEnumerable <Order> GetPossibleMatch(PositionSummary up);
public static void SetSell(this Trader t, PositionSummary p, bool isSelling) { var k = MakeKey(t, p); sellDic.Set(k, isSelling); }