/// <summary> /// 傳送下單命令 /// </summary> /// <param name="action">下單進出場動作</param> /// <param name="category">下單類型</param> /// <param name="limitPrice">限價價格(市價=0)</param> /// <param name="lots">下單數量</param> /// <param name="isReverse">是否需反轉倉位</param> /// <param name="touchPrice">觸發或停損價格</param> /// <param name="name">下單註解</param> /// <param name="openNextBar">是否開倉在下一根 Bars</param> public bool Send(EOrderAction action, OrderCategory category, double limitPrice, int lots, bool isReverse, double touchPrice = 0, string name = null, bool openNextBar = false) { limitPrice = Math.Round(limitPrice, __iDecimalPoint); TradeOrder cTrust = __cEntrusts.GetTradeFromName(name); if (cTrust != null) { if (openNextBar) { __cNextBarRequires.Add(name); //標記 NextBar 時, 可以下單 return true; } else { if (cTrust.Price == limitPrice) { //委託價格一樣就忽略 return false; } else { if (cTrust.IsTrusted && !cTrust.IsDealed) { //如果已經委託完成且尚未成交就取消單號 this.SendCancel(cTrust); } else { //如果還沒有委託成功 return false; //直接離開(可能需要等到委託成功之後才能處理) } } } } TradeOrder cOrder = new TradeOrder(); //建立預約委託單的資訊 cOrder.Action = action; cOrder.BarNumber = Bars.CurrentBar; cOrder.Category = category; cOrder.Contracts = lots; cOrder.Name = name; cOrder.Price = limitPrice; cOrder.IsReverse = isReverse; cOrder.SymbolId = Bars.Request.Symbol; cOrder.Time = Bars.Time.Value; cOrder.Ticket = (openNextBar) ? name : GetTrustID(); __cEntrusts.Add(cOrder); //加入至委託列表內 if (openNextBar) { //如果需要在下一根 Bars 下單, 就先保留 name 在佇列, 以方便比對委託單 __cReserves.Enqueue(name); __cNextBarRequires.Add(name); } else { if (isReverse) { //如果有反轉倉單 CancelLimit(action); //取消所有反向之前的限價委託單 } this.SendTrust(cOrder); //傳送新委託單(模擬成交) } return true; }
public void OnTrade(Trade trade) { if (_trades == null) { _trades = new TradeList(trade.CurrencyPair); } _trades.Add(trade); OutputDisruptor.Publish(trade); Log.Debug("Trade received: " + trade.ToString()); }
public void ExecuteTrade(Order order, List <Order> matchingOrders) { Trade trade = new Trade(order.Symbol, order.Exchange); long quantityRequired = order.Quantity; //if (order.Transaction == TransactionType.Buy) { foreach (var sOrder in matchingOrders) { //Single seller has sufficient Quantity if (quantityRequired <= sOrder.Quantity) { trade.UpdateTrade(sOrder.Price, quantityRequired); } else { trade.UpdateTrade(sOrder.Price, sOrder.Quantity); } if (quantityRequired == trade.Quantity || sOrder.Quantity == trade.Quantity) { //Trade Finished TradeCompleted?.Invoke(this, new TradeCompletedEventArgs(trade)); if (order.Quantity == trade.Quantity) { sOrder.Quantity -= trade.Quantity; order.Status = OrderStatus.Completed; order.OrderSubmitted(OrderStatus.Completed); if (sOrder.Quantity == 0) { sOrder.Status = OrderStatus.Completed; } } else { order.Quantity -= trade.Quantity; sOrder.Status = OrderStatus.Completed; sOrder.OrderSubmitted(OrderStatus.Completed); } break; } } TradeList.Add(trade); } }
/// <summary> /// 傳送下單命令 /// </summary> /// <param name="action">下單進出場動作</param> /// <param name="category">下單類型</param> /// <param name="limitPrice">限價價格(市價=0)</param> /// <param name="lots">下單數量</param> /// <param name="isReverse">是否需反轉倉位</param> /// <param name="touchPrice">觸發或停損價格</param> /// <param name="name">下單註解</param> /// <param name="openNextBar">是否開倉在下一根 Bars</param> public virtual bool Send(EOrderAction action, OrderCategory category, double limitPrice, int lots, bool isReverse, double touchPrice = 0, string name = null, bool openNextBar = false) { if (this.Bars.IsLastBars) { //檢查是否下單類型是平倉單或是反轉單(如果是平倉單需要檢查委託倉內的所有同向平倉單是否超過留倉數量, 如果是反轉單要取消所有開倉委託) if (isReverse || action == EOrderAction.Sell || action == EOrderAction.BuyToCover) { int iLots = 0; if (!isReverse) { iLots = __cCurrentPosition.OpenLots; if (lots > iLots) { //檢查委託數量是否超過開倉量 return false; } else { iLots -= lots; //先將開倉數量減去委託數量 } } int iCount = __cEntrusts.Count; if (iCount > 0) { bool bRet = isReverse; for (int i = 0; i < iCount; i++) { TradeOrder cTemp = __cEntrusts[i]; if (isReverse) { //如果是反轉單(取消所有新倉單) if (cTemp.IsTrusted && !cTemp.IsCancel && cTemp.Contracts > 0 && (cTemp.Action == EOrderAction.Buy || cTemp.Action == EOrderAction.SellShort)) { cTemp.IsCancel = SendTrust(cTemp, true); } } else if (cTemp.Contracts > 0 && cTemp.Action == action && !cTemp.Name.Equals(name)) { iLots -= cTemp.Contracts; if (iLots < 0) { bRet = true; break; } } } if (bRet) { return false; } } } limitPrice = Math.Round(limitPrice, __iDecimalPoint); TradeOrder cTrust = __cEntrusts.GetTradeFromName(name); if (cTrust != null) { if (openNextBar) { if (!cTrust.IsSended) { cTrust.Price = limitPrice; //支援可以下出 NextBar 的限價單(沒有指定會以 0 送出) __cNextBarRequires.Add(name); //標記 NextBar 時, 可以下單 return true; } } else { if (cTrust.Price == limitPrice) { return true; } else { //委託價格不一樣才處理 if (cTrust.IsTrusted && !cTrust.IsCancel) { //如果已經委託完成就取消單號 cTrust.IsCancel = SendTrust(cTrust, true); //向下單機傳送取消委託單的命令 } } } return false; } TradeOrder cOrder = new TradeOrder(); //建立預約委託單的資訊 cOrder.Action = action; cOrder.BarNumber = Bars.CurrentBar; cOrder.Category = category; cOrder.Contracts = lots; cOrder.Name = name; cOrder.Price = limitPrice; cOrder.IsReverse = isReverse; cOrder.SymbolId = GetOrderSymbol(); cOrder.Time = DateTime.Now; cOrder.Ticket = (openNextBar) ? name : GetTrustID(); __cEntrusts.Add(cOrder); //加入至委託列表內 bool bReturn = true; if (openNextBar) { //如果需要在下一根 Bars 下單, 就先保留 name 在佇列, 以方便比對委託單 __cReserves.Enqueue(name); __cNextBarRequires.Add(name); } else { bReturn = SendTrust(cOrder); //傳送新委託單給下單機 } return bReturn; } return false; }