Esempio n. 1
0
        private TradeOrder SplitOrder(TradeOrder source, int splitContracts)
        {
            TradeOrder cTradeOrder = source.Clone();             //將原始下單資訊 Clone 一份

            cTradeOrder.Contracts = splitContracts;              //修改成要分拆的數量

            int iContracts = source.Contracts;

            if (iContracts > 1)                //如果原始的量超過 1 就計算手續費跟交易稅的平均值(有可能成交數量 > 1, 手續費與交易稅會合併計算)
            {
                cTradeOrder.Fee = source.Fee / iContracts * splitContracts;
                cTradeOrder.Tax = source.Tax / iContracts * splitContracts;
                source.Fee     -= cTradeOrder.Fee;
                source.Tax     -= cTradeOrder.Tax;
            }

            source.Contracts -= splitContracts; //分拆後的數量要從原始的下單資訊內扣除
            return(cTradeOrder);                //回傳分拆後的下單資訊
        }
Esempio n. 2
0
        /// <summary>
        ///   計算倉位
        /// </summary>
        /// <param name="queue">儲存留倉資訊的 Queue</param>
        /// <param name="trade">交易資訊</param>
        private void CalculatePosition(Queue <Trade> queue, Trade trade)
        {
            lock (queue) {
                TradeOrder cTargetOrder = trade._EntryOrder;
                while (queue.Count > 0 && cTargetOrder.Contracts > 0)
                {
                    Trade      cTrade      = queue.Peek();
                    TradeOrder cTradeOrder = cTrade._EntryOrder;

                    if (cTradeOrder.Contracts > cTargetOrder.Contracts)                      //如果留倉單數量大於平倉單成交數量
                    {
                        trade._ExitOrder  = cTargetOrder;                                    //將平倉單直接放入 _ExitOrder
                        trade._EntryOrder = SplitOrder(cTradeOrder, cTargetOrder.Contracts); //從留倉單 Clone 後拆出與平倉單相同的數量, 放入 _EntryOrder
                        trade.CalculateProfit(__dBigPointValue);                             //計算利潤

                        lock (__cHistorys) {
                            __cHistorys.Add(trade);                              //寫入歷史資訊列表
                        }

                        SetParameters(trade);     //計算內部其他參數
                        break;                    //直接離開(因為已經從倉部位扣掉平倉數量, 所以直接離開)
                    }
                    else                          //如果留倉單數量小於或等於平倉單數量
                    {
                        cTrade.IsTradeClosed = true;
                        cTrade._ExitOrder    = SplitOrder(cTargetOrder, cTradeOrder.Contracts); //將平倉單 Clone 後拆出與留倉單相同數量, 放入 _ExitOrder
                        cTrade.CalculateProfit(__dBigPointValue);                               //計算利潤

                        lock (__cHistorys) {
                            __cHistorys.Add(cTrade);                              //寫入歷史資訊列表
                        }

                        SetParameters(cTrade);                    //計算內部其他參數
                        queue.Dequeue();                          //將此筆留倉單從 queue 內移除(表示此筆留倉單已經被沖銷)
                        this.Remove(cTradeOrder.Ticket);          //被沖銷的留倉單就從倉部位內移除掉
                    }
                }
            }
        }
Esempio n. 3
0
		private void LargeOrderService_onResponse(object sender, ResponseEvent e) {
			switch (e.ResponseType) {
				case ResponseType.Cancel:
					lock (__oLock) {
						if (__cCurrent != null) {
							EOrderAction cAction = __cCurrent.Action;
							__cTemp = (__bReverse && (cAction == EOrderAction.Sell || cAction == EOrderAction.BuyToCover)) ? null : __cCurrent;
						}
						__cCurrent = null;
					}
					break;
				case ResponseType.Deal:
					lock (__oLock) {
					        if (__cCurrent != null && __cCurrent.Contracts == 0) {
							__cTemp = null;
							__cCurrent = null;
					        }
					}
					break;
				case ResponseType.Trust:
					lock (__oLock) {
						if (__cCurrent == null) {
							__cTemp = null;
							__cCurrent = e.TradeOrder as TradeOrder;
						}
					}
					break;
			}
		}
Esempio n. 4
0
		private void PipeStream_onMessage(object sender, MessageEvent e) {
			if (e.Buffer[0] == 0x7b) {  //檢查是否為 JSON 開頭符號
				JToken cToken = JsonConvert.DeserializeObject<JToken>(e.Message);
				int iDataType = cToken["Type"].Value<int>();

				switch (iDataType) {
					case 0: //接收 REPOTR 完畢的回報類型(如果沒收到此命令會無窮盡等待)
						__cResetEvent.Set();
						if (logger.IsInfoEnabled) logger.Info("[Report] Order data response completed...");
						break;
					case 1: //委託回報
						string sOrderSymbolId = null;
						OrderTrust[] cTrusts = cToken["Report"].ToObject<OrderTrust[]>();
						foreach (OrderTrust cTrust in cTrusts) {
							string sTrustId =  cTrust.委託書號;
							int iTrustCount = cTrust.未成交數量;
							
							TradeOrder cTrustOrder = __cEntrusts.GetTrade(sTrustId);  //取得委託單
							if (cTrustOrder == null && iTrustCount > 0) {  //委託未成交數量大於0才處理
								string sSymbolId = cTrust.商品代號;
								
								cTrustOrder = GetWaiting(sSymbolId, cTrust.委託價格);  //取得等待委託回報的委託單(這些委託單都要等待委託單號)
								if (cTrustOrder == null) {
									if (__iMaxTrustIndex == __iTrustIndex) {  //相等表示沒有下出任何的委託單, 可能是留在下單機內的委託單
										if (sOrderSymbolId == null) {
											sOrderSymbolId = GetOrderSymbol();
										}

										if (CheckSymbol(sSymbolId, sOrderSymbolId)) {  //比對兩個商品代號是否相同, 相同才會被加入委託倉內
											cTrustOrder = new TradeOrder();
											cTrustOrder.IsSended = true;
											cTrustOrder.IsTrusted = true;
											cTrustOrder.Name = sTrustId;
											cTrustOrder.Ticket = sTrustId;
											cTrustOrder.SymbolId = sSymbolId;
											cTrustOrder.Price = cTrustOrder.Price;
											cTrustOrder.Contracts = iTrustCount;
											cTrustOrder.Time = cTrust.委託時間;
											cTrustOrder.Category = (cTrustOrder.Price == 0) ? OrderCategory.Market : OrderCategory.Limit;
											
											if (cTrust.倉別.Equals(__sClosedString)) {
												cTrustOrder.Action = (cTrust.買賣別) ? EOrderAction.BuyToCover : EOrderAction.Sell;
											} else {
												cTrustOrder.Action = (cTrust.買賣別) ? EOrderAction.Buy : EOrderAction.SellShort;
											}
											__cEntrusts.Add(cTrustOrder);  //儲存至委託陣列內
										}
									} else {
										continue;
									}
								} else {
									cTrustOrder.IsTrusted = true;   //true=委託成功
									cTrustOrder.Ticket = sTrustId;  //填入回報來的委託單號
									cTrustOrder.Time = cTrust.委託時間;
									
									__cEntrusts.Add(cTrustOrder);   //儲存至委託陣列內
								}
							}

							if (cTrustOrder != null) {
								bool bDelete = cTrust.是否刪單;
								if (bDelete) {
									__cEntrusts.Remove(sTrustId);  //從委託陣列內移除委託
								}

								OnResponse(cTrustOrder, cTrustOrder.SymbolId, (bDelete) ? ResponseType.Cancel : ResponseType.Trust);
								if (logger.IsInfoEnabled) logger.InfoFormat("[Trust] #{0} {1} {2} {3} at {4} {5} @{6}", cTrustOrder.Ticket, cTrustOrder.SymbolId, cTrustOrder.Action, (bDelete) ? cTrustOrder.Contracts : iTrustCount, cTrustOrder.Price, (bDelete) ? cTrust.備註 : (iTrustCount == 0) ? __sFullDeal : cTrustOrder.Name, cTrustOrder.Time.ToString("yyyy-MM-dd HH:mm:ss"));
							}
						}
						break;
					case 2: //成交回報
						OrderDeal cDeal = cToken["Report"].ToObject<OrderDeal>();
						string sDealId = cDeal.成交書號;  //成交書號 == 委託書號

						TradeOrder cTempTrust = __cEntrusts.GetTrade(sDealId);
						if (cTempTrust != null) {  //檢查委託陣列內是否有相同的成交書號(委託書號)
							int iDealLots = cDeal.成交數量;
							cTempTrust.Contracts -= iDealLots;

							bool bDealed = cTempTrust.Contracts == 0;
							if (bDealed) {
								OnResponse(cTempTrust, cTempTrust.SymbolId, ResponseType.Trust);
								if (logger.IsInfoEnabled) logger.InfoFormat("[Trust] #{0} {1} {2} {3} at {4} {5} @{6}", cTempTrust.Ticket, cTempTrust.SymbolId, cTempTrust.Action, 0, cTempTrust.Price, __sFullDeal, cTempTrust.Time.ToString("yyyy-MM-dd HH:mm:ss"));
							}

							TradeOrder cDealOrder = cTempTrust.Clone();
							cDealOrder.IsDealed = cTempTrust.Contracts == 0;
							cDealOrder.Contracts = iDealLots;
							cDealOrder.Price = cDeal.成交價格;
							cDealOrder.Fee = cDeal.手續費;
							cDealOrder.Tax = cDeal.交易稅;
							cDealOrder.Time = cDeal.成交時間;
							
							double[] dValues = CalculateCommissions(cDealOrder);  //計算其他佣金與手續費(通常真實交易會回報交易稅與眷商手續費, 這裡還可以計算其他的附加費用或是附加的手續費)
							cDealOrder.OtherFees = dValues[0];
							cDealOrder.Fee += dValues[1];
							if (logger.IsInfoEnabled) logger.InfoFormat("[Deal] #{0} {1} {2} {3} at {4} {5} @{6}", cDealOrder.Ticket, cDealOrder.SymbolId, cDealOrder.Action, cDealOrder.Contracts, cDealOrder.Price, cDealOrder.Name, cDealOrder.Time.ToString("yyyy-MM-dd HH:mm:ss"));
							
							lock (__cDeals) {
								__cDeals.Enqueue(cDealOrder);
							}
							cTempTrust.IsDealed = true;
						}
						break;
				}
			}
		}
Esempio n. 5
0
		private bool CheckTrust(EOrderAction action, OrderCategory category, double limitPrice, int lots, string name, bool isReverse, bool openNextBar) {
			TradeOrder cTrust = __cEntrusts.GetTradeFromName(name);
			if (cTrust == null) {
				if (action == EOrderAction.Sell || action == EOrderAction.BuyToCover) {
					bool bRet = false;
					int iCount = __cEntrusts.Count;
					if (iCount > 0) {
						EOrderAction cAction = (action == EOrderAction.Buy || action == EOrderAction.BuyToCover) ? EOrderAction.SellShort : (action == EOrderAction.SellShort || action == EOrderAction.Sell) ? EOrderAction.Buy : action;
						for (int i = 0; i < iCount; i++) {
							TradeOrder cTemp = __cEntrusts[i];
							if (cTemp.IsTrusted && cTemp.Action == cAction && cTemp.Contracts > 0) {
								if (!cTemp.IsCancel) {
									SendTrust(cTemp, cTemp.Ticket);  //取消委託單
									cTemp.IsCancel = true;
								}
								bRet = true;
							}
						}
					}

					if (bRet || __cDeals.Count > 0) {
						return false;
					}
				}
			} else {
				if (openNextBar) {
					if (!cTrust.IsSended) {
						cTrust.Price = limitPrice;  //支援可以下出 NextBar 的限價單(沒有指定會以 0 送出)
						__cNextBarRequires.Add(name);  //標記 NextBar 時, 可以下單
						return true;
					}
					return false;
				} else {
					if (cTrust.Price == limitPrice) {  //委託價格一樣就忽略
						return false;
					} else {
						if (cTrust.IsTrusted && !cTrust.IsCancel) {  //如果已經委託完成就取消單號
							SendTrust(cTrust, cTrust.Ticket);  //向下單機傳送取消委託單的命令
							cTrust.IsCancel = 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);  //加入至委託列表內

			if (openNextBar) {  //如果需要在下一根 Bars 下單, 就先保留 name 在佇列, 以方便比對委託單
				__cReserves.Enqueue(name);
				__cNextBarRequires.Add(name);
			} else {
				if (__cCloseOrder == null) {
					SendTrust(cOrder);  //傳送新委託單給下單機
				}
			}
			return true;
		}
Esempio n. 6
0
		internal void SendTrust(TradeOrder trust, string cancelTicket = null) {
			EOrderAction cAction = trust.Action;
			bool bClose = cAction == EOrderAction.Sell || cAction == EOrderAction.BuyToCover;
			StringBuilder cBuilder = new StringBuilder(128);
			cBuilder.Append(__sLocalPipe).Append(",")
				.Append(trust.SymbolId).Append(",")
				.Append(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")).Append(",")
				.Append((cAction == EOrderAction.Buy || cAction == EOrderAction.BuyToCover) ? 'B' : (cAction == EOrderAction.Sell || cAction == EOrderAction.SellShort) ? 'S' : ' ').Append(",")
				.Append(trust.Contracts).Append(",")
				.Append(trust.Price).Append(",")
				.Append((cancelTicket != null) ? -1 : (bClose) ? 0 : 1).Append(",")
				.Append(Bars.Close[0]).Append(",")
				.Append((cancelTicket == null) ? (trust.IsReverse) ? "1" : "0" : cancelTicket);

			string sCommand = cBuilder.ToString();
			__cPipeStream.Send(__sApiPipe, sCommand);  //發送委託單命令給下單機
			if (logger.IsInfoEnabled) logger.InfoFormat("[RealOrderService.Send] {0}", sCommand);

			trust.IsSended = true;  //設定已經傳送完畢
			if (bClose) {  //如果是平倉單
				__cCloseOrder = trust;  //指定平倉單至變數內(模組會監測平倉單完畢後才會啟動之後的單做下單動作, 避免倉部位錯亂)
			}
		}
Esempio n. 7
0
		public override void OnWork() {
			if (Bars.IsLastBars) {
				if (Bars.CurrentBar > __iPrevious) {
					SendNextBars(__iPrevious);  //處理 NextBars 下單程序
					__iPrevious = Bars.CurrentBar;
				}

				HashSet<string> cSwap = __cPNextBarRequires;  //將上一個條件狀態保留起來
				__cPNextBarRequires = __cNextBarRequires;  //將目前條件狀態置換到上一個條件狀態變數內
				__cNextBarRequires = cSwap;  //將上一個狀態置換到目前狀態上(減少使用 new 而造成 GC 負擔)
				__cNextBarRequires.Clear();  //清除狀態並等待下一輪 CalcBar 時儲存新條件狀態

				if (__cCloseOrder != null && (__cCloseOrder.IsCancel || __cCloseOrder.Contracts == 0)) {
					bool bClear = true;
					int iCount = __cEntrusts.Count;
					if (iCount > 0) {
						bool bCancel =  __cCloseOrder.IsCancel;
						for (int i = iCount - 1; i >= 0; i--) {  //迴圈由最後一筆往前取得(避免 GetWaiting 取出後刪單造成取得順序問題)
							TradeOrder cTemp = __cEntrusts[i];
							if (bCancel && !cTemp.IsSended) {  //如果目前的平倉單被取消, 而且此單在倉閘內尚未傳送
								GetWaiting(cTemp.SymbolId, cTemp.Price);  //直接從委託倉閘內取出(放棄此單, 因為尚未送出可以直接取出並放棄)
								continue;
							} else if (!cTemp.IsSended && cTemp.Ticket != cTemp.Name) {  //如果此單尚未送出而且 Ticket 與 Name 都不同(相同表示可能是下 NextBar 單而且尚未傳送, 這些單還不能傳送)
								SendTrust(cTemp);
							}
							
							if (bClear) {
								bClear = cTemp.IsTrusted && cTemp.IsDealed;  //平倉完成後需要檢查委託倉內是否全部的單都有成交動作(如果有反向單則成交了才能改變倉位方向, 所以必須檢查是否全部委託單是否已經開始成交)
							}
						}
					}

					if (bClear) {  //如果所有的單都已經開始成交或是已經無單, 表示可以清除此平倉變數
						__cCloseOrder = null;
					}
				}

				if (__cCloseOrder == null) {  //沒有平倉內容才可以計算成交部位(這樣倉位方向才不會算錯)
					CalculatePositions();  //計算成交部位狀況
				}
				AsyncCalculateProfits();  //計算留倉部位損益
			}
		}
Esempio n. 8
0
		private void SetTax(TradeOrder deal) {
			double dTotals = deal.Price * __cProperty.BigPointValue * deal.Contracts;
			ITax cTax = __cProperty.TaxRule as ITax;
			deal.Tax = cTax.GetTax(dTotals);
		}
Esempio n. 9
0
		private void SendTrust(TradeOrder trust, double dealPrice = 0) {
			trust.IsTrusted = true;
			if (logger.IsInfoEnabled) logger.InfoFormat("[Trust] #{0} {1} {2} {3} at {4} {5} @{6}", trust.Ticket, trust.SymbolId, trust.Action, trust.Contracts, trust.Price, trust.Name, trust.Time.ToString("yyyy-MM-dd HH:mm:ss"));
			
			if (trust.Price == 0) {  //市價成交
				OrderDeal(trust, dealPrice);
			} else {
				SendLimit(trust);
			}
		}
Esempio n. 10
0
		private void SendLimit(TradeOrder trust) {
			double dDealPrice = 0, dPrice = trust.Price;
			EOrderAction cAction = trust.Action;
			if (cAction == EOrderAction.Buy || cAction == EOrderAction.BuyToCover) {
				dDealPrice = (dPrice >= Bars.Close[0]) ? Bars.Close[0] : (dPrice >= Bars.Low[0]) ? dPrice : 0;
			} else {
				dDealPrice = (Bars.Close[0] >= dPrice) ? Bars.Close[0] : (Bars.High[0] >= dPrice) ? dPrice : 0;
			}

			if (dDealPrice > 0) {
				OrderDeal(trust, dDealPrice);
			}
		}
Esempio n. 11
0
		private void OrderDeal(TradeOrder trust, double dealPrice = 0) {
			trust.IsDealed = true;

			TradeOrder cDeal = trust.Clone();
			cDeal.Price = (dealPrice == 0) ? Bars.Close[0] : dealPrice;
			cDeal.Time = Bars.Time[0];
			SetTax(cDeal);
			
			double[] dValues = CalculateCommissions(cDeal);  //計算交易佣金與手續費用(由策略使用者自行決定的佣金與手續費設定所計算出來的價格)
			cDeal.OtherFees = dValues[0];
			cDeal.Fee = dValues[1];

			__cDeals.Enqueue(cDeal);
		}
Esempio n. 12
0
		private bool CheckTrust(EOrderAction action, OrderCategory category, double limitPrice, int lots, string name, bool isReverse, bool openNextBar) {
			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) {  //如果已經委託完成就取消單號
							string sTicket = cTrust.Ticket;  //委託單號
							AdjustClosedContract(cTrust);  //調整平倉數量(如果是平倉單就要調整)
							__cEntrusts.Remove(cTrust.Ticket);  //從委託陣列中移除
						} else {  //如果還沒有委託成功
							return false;  //直接離開(可能需要等到委託成功之後才能處理)
						}
					}
				}
			}

			if (action == EOrderAction.Sell || action == EOrderAction.BuyToCover) {
				int iLots = __cCurrentPosition.OpenLots - __iUsedClosedTempLots;  //檢查平倉數量是否足夠
				if (lots > iLots) {  //平倉數量不足(不下單)
					return false;
				} else {
					lock (__oTempLock) {
						__iUsedClosedTempLots += lots;
					}
				}
			}

			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[0];
			cOrder.Ticket = (openNextBar) ? name : GetTrustID();
			__cEntrusts.Add(cOrder);  //加入至委託列表內

			if (openNextBar) {  //如果需要在下一根 Bars 下單, 就先保留 name 在佇列, 以方便比對委託單
				__cReserves.Enqueue(name);
				__cNextBarRequires.Add(name);
			} else {
				if (isReverse) {  //如果有反轉倉單
					CancelLimit(action);  //取消所有反向之前的限價委託單
				}
				SendTrust(cOrder);  //傳送新委託單給下單機
			}
			return true;
		}
Esempio n. 13
0
		private void AdjustClosedContract(TradeOrder order) {
			EOrderAction cAction = order.Action;
			if (cAction == EOrderAction.Sell || cAction == EOrderAction.BuyToCover) {
				lock (__oTempLock) {
					if (__iUsedClosedTempLots > 0) {
						__iUsedClosedTempLots -= order.Contracts;
					}
				}
			}
		}