protected override void CalcBar() { // 只在 Data2 有資料後才處理分線 if (Data2.CurrentBar <= 1 || Bars.Info.Resolution.Type != EResolution.Minute) { return; } 漲跌.Value = Bars.Close[0] - Bars.Open[0]; 漲跌幅.Value = 100 * ((Bars.Close[0] - Bars.Close[1]) / Bars.Close[1]); 上影線.Value = Bars.High[0] - Math.Max(Bars.Open[0], Bars.Close[0]); 下影線.Value = Math.Min(Bars.Open[0], Bars.Close[0]) - Bars.Low[0]; 實體線.Value = Math.Abs(Bars.Open[0] - Bars.Close[0]); 成交日期 = int.Parse(Bars.Time[0].Date.ToString("yyyyMMdd")); 成交時間 = int.Parse(Bars.BarUpdateTime.ToString("HHmmss")); string m_資料時間 = Bars.BarUpdateTime.ToString("HH:mm:ss"); if (設定_啟用詳細訊息 && 設定_輸出集合 == null) { 設定_輸出集合 = new Dictionary<string, string>(); 設定_輸出集合.Add("輸出記錄", "參數設定"); 設定_輸出集合.Add("策略名稱", 設定_策略名稱); 設定_輸出集合.Add("策略版本", 設定_策略版本); #region 輸出指標策略參數 設定_輸出集合.Add("作多參數", 作多參數.ToString()); 設定_輸出集合.Add("作空參數", 作空參數.ToString()); 設定_輸出集合.Add("作多天數", 作多天數.ToString()); 設定_輸出集合.Add("作空天數", 作空天數.ToString()); 設定_輸出集合.Add("啟用指標停損", 啟用指標停損.ToString()); #endregion 設定_輸出集合.Add("啟用順勢進場", 啟用順勢進場.ToString()); 設定_輸出集合.Add("順勢進場週間日", 順勢進場週間日); 設定_輸出集合.Add("啟用逆勢進場", 啟用逆勢進場.ToString()); 設定_輸出集合.Add("逆勢進場週間日", 逆勢進場週間日); 設定_輸出集合.Add("結算隔日進場月份", 結算隔日進場月份); 設定_輸出集合.Add("資金_管理模式", 資金_管理模式.ToString()); 設定_輸出集合.Add("資金_風險比例", 資金_風險比例.ToString()); 設定_輸出集合.Add("資金_基本規模", 資金_基本規模.ToString()); 設定_輸出集合.Add("資金_跳空倍注", 資金_跳空倍注.ToString()); 設定_輸出集合.Add("資金_均多倍注", 資金_均多倍注.ToString()); 設定_輸出集合.Add("資金_均空倍注", 資金_均空倍注.ToString()); 設定_輸出集合.Add("資金_逆勢倍注", 資金_逆勢倍注.ToString()); 設定_輸出集合.Add("濾網_啟用多單", 濾網_啟用多單.ToString()); 設定_輸出集合.Add("濾網_啟用空單", 濾網_啟用空單.ToString()); 設定_輸出集合.Add("濾網_啟用當沖", 濾網_啟用當沖.ToString()); 設定_輸出集合.Add("濾網_開盤區間時間", 濾網_開盤區間時間.ToString()); 設定_輸出集合.Add("濾網_停單時間", 濾網_停單時間.ToString()); 設定_輸出集合.Add("加減碼_停損金額", 加減碼_停損金額.ToString()); 設定_輸出集合.Add("加減碼_停損點數", 停損點數.ToString()); 設定_輸出集合.Add("加減碼_加碼點數", 加減碼_加碼點數.ToString()); 設定_輸出集合.Add("加減碼_加碼次數", 加減碼_加碼次數.ToString()); 輸出詳細內容(); } // 換日後需重算關鍵數值 if (Bars.Time[0].Date > Bars.Time[1].Date && 重算日期 < 成交日期) { if (設定_啟用詳細訊息) { 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出記錄", "新交易日"); 設定_輸出集合.Add("原交易日", Bars.Time[1].Date.ToString("yyyy-MM-dd")); 設定_輸出集合.Add("新交易日", Bars.Time[0].Date.ToString("yyyy-MM-dd")); 設定_輸出集合.Add("資料時間", m_資料時間); 輸出詳細內容(); } 重算日期 = 0; } if (重算日期 == 0) { // 如非換日所引起的重算動作就跳出 if (Bars.Time[0].Date < Bars.Time[1].Date) { return; } 昨最高 = Data2.High[0]; 昨最低 = Data2.Low[0]; 昨收盤 = Data2.Close[0]; 今開盤 = Bars.Open[0]; 開高價 = Bars.High[0]; 開低價 = Bars.Low[0]; 開收盤 = Bars.Close[0]; 開漲跌 = Bars.Open[0] - Data2.Close[0]; 開漲跌幅 = 100 * (開漲跌 / Data2.Close[0]); 開盤區間高點 = 0; 開盤區間低點 = int.MaxValue; ATR = AvgTrueRange.AverageTrueRange(this, 14, 0, 2); 當日作多次數 = 0; 當日作空次數 = 0; 前次PositionSide = EMarketPositionSide.Flat; 今最高 = Bars.High[0]; 今最低 = Bars.Low[0]; 今日停單 = false; 週間日 = Bars.Time[0].DayOfWeek; // 資金管理:依模式計算下單規模 double m_可用金額 = InitialCapital + NetProfit; double m_冒險金額 = m_可用金額 * 資金_風險比例; double m_市場風險 = 0; 下單規模 = 資金_基本規模; switch (資金_管理模式) { case 0: // 固定規模 下單規模 = 資金_基本規模; break; case 1: // 以保證金為基礎計算下單規模 m_市場風險 = Bars.Info.Margin; 下單規模 = Math.Max((int)Math.Floor(m_冒險金額 / m_市場風險), 資金_基本規模); break; case 2: // 以波動度為基礎計算下單規模 m_市場風險 = ATR * Bars.Info.BigPointValue; 下單規模 = Math.Max((int)Math.Floor(m_冒險金額 / m_市場風險), 資金_基本規模); break; } if (資金_跳空倍注 > 0 && 開漲跌幅 >= 資金_跳空倍注) { 下單規模 *= 2; } if (資金_均多倍注 > 0 && 開收盤 > Data2.Close.Average(資金_均多倍注)) { 下單規模 *= 2; } if (資金_均空倍注 > 0 && 開收盤 < Data2.Close.Average(資金_均空倍注)) { 下單規模 *= 2; } #region 計算指標策略數值1 // 原版 Dual Thrust 公式 計算DualThrust(作多天數); 作多區間 = 開收盤 + 作多參數 * Math.Max(m_HH - m_LC, m_HC - m_LL); 計算DualThrust(作空天數); 作空區間 = 開收盤 - 作空參數 * Math.Max(m_HH - m_LC, m_HC - m_LL); // 若 作多區間 - 作空區間 小於商品的 0.2% 幅度,今日就停單 if (作多區間 - 作空區間 < 今開盤 * 0.002) { 今日停單 = true; } if (設定_啟用詳細訊息) { 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出記錄", "指標數值"); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("作多區間", 作多區間.ToString()); 設定_輸出集合.Add("作空區間", 作空區間.ToString()); 輸出詳細內容(); } #endregion // 本交易日開倉,但不在進場月份中就停單 if (結算日集合.ContainsKey(Bars.Time[1].Date) && !結算隔日進場月份集合[Bars.Time[0].Date.Month]) { 今日停單 = true; } if (設定_啟用詳細訊息 && 今日停單) { 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出記錄", "今日停單"); 設定_輸出集合.Add("日期", Bars.Time[0].ToString("yyyy-MM-dd")); 設定_輸出集合.Add("停單", 今日停單.ToString()); 輸出詳細內容(); } if (設定_啟用詳細訊息) { 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出記錄", "下單規模"); 設定_輸出集合.Add("口數", 下單規模.ToString()); 輸出詳細內容(); } 重算日期 = 成交日期; } // 若仍無重算日期記錄就跳出 if (重算日期 == 0) { return; } 今最高 = Math.Max(今最高, Bars.High[0]); 今最低 = Math.Min(今最低, Bars.Low[0]); #region 計算指標策略數值2 #endregion // 開盤區間內只記錄高低價,不判斷訊號 if (濾網_開盤區間時間 > 0 && 成交時間 <= 濾網_開盤區間時間) { 開盤區間高點 = Math.Max(開盤區間高點, Bars.High[0]); 開盤區間低點 = Math.Min(開盤區間低點, Bars.Low[0]); return; } if (CurrentPosition.Side == EMarketPositionSide.Long && 前次PositionSide == EMarketPositionSide.Flat) { 當日作多次數++; } if (CurrentPosition.Side == EMarketPositionSide.Short && 前次PositionSide == EMarketPositionSide.Flat) { 當日作空次數++; } // 判斷順勢進場新單訊號 if (啟用順勢進場 == 1) { #region 順勢進場新單訊號 if (CurrentPosition.Side == EMarketPositionSide.Flat && CurrentPosition.OpenTrades.Count == 0 && 成交時間 <= 濾網_停單時間 && !今日停單) { if (濾網_啟用多單 == 1 && 當日作多次數 == 0 && Bars.Close[0] >= 作多區間 && 順勢進場週間日集合[週間日]) { 下單名稱 = "突破作多"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("作多區間", 作多區間.ToString()); 設定_輸出集合.Add("下單規模", 下單規模.ToString()); 輸出詳細內容(); } 多單.Send(下單名稱, 下單規模); } if (濾網_啟用空單 == 1 && 當日作空次數 == 0 && Bars.Close[0] <= 作空區間 && 順勢進場週間日集合[週間日]) { 下單名稱 = "跌破作空"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("作多區間", 作多區間.ToString()); 設定_輸出集合.Add("下單規模", 下單規模.ToString()); 輸出詳細內容(); } 空單.Send(下單名稱, 下單規模); } } #endregion } // 判斷逆勢進場新單訊號 if (啟用逆勢進場 == 1) { #region 逆勢進場新單訊號 #endregion } // 判斷多單是否需要加碼 if (CurrentPosition.Side == EMarketPositionSide.Long && CurrentPosition.OpenTrades.Count <= 加減碼_加碼次數) { if (Bars.Close[0] >= 最後進場部位.Price + 加減碼_加碼點數) { 下單名稱 = "多單加碼"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("最後進場點位", 最後進場部位.Price.ToString()); 設定_輸出集合.Add("加碼點位", (最後進場部位.Price + 加減碼_加碼點數).ToString()); 設定_輸出集合.Add("下單規模", ((資金_逆勢倍注 == 1) ? 下單規模 * 2 : 下單規模).ToString()); 輸出詳細內容(); } 多單.Send(下單名稱, 最後進場部位.Contracts); } } // 判斷空單是否需要加碼 if (CurrentPosition.Side == EMarketPositionSide.Short && CurrentPosition.OpenTrades.Count <= 加減碼_加碼次數) { if (Bars.Close[0] <= 最後進場部位.Price - 加減碼_加碼點數) { 下單名稱 = "空單加碼"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("最後進場點位", 最後進場部位.Price.ToString()); 設定_輸出集合.Add("加碼點位", (最後進場部位.Price - 加減碼_加碼點數).ToString()); 設定_輸出集合.Add("下單規模", ((資金_逆勢倍注 == 1) ? 下單規模 * 2 : 下單規模).ToString()); 輸出詳細內容(); } 空單.Send(下單名稱, 最後進場部位.Contracts); } } // 判斷多單是否需要停損 if (CurrentPosition.Side == EMarketPositionSide.Long && CurrentPosition.OpenTrades.Count > 0) { if (Bars.Close[0] <= 最後進場部位.Price - 停損點數) { 下單名稱 = "多單停損"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱 + "_虧損"); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("最後進場點位", 最後進場部位.Price.ToString()); 設定_輸出集合.Add("停損點位", (最後進場部位.Price - 停損點數).ToString()); 輸出詳細內容(); } 多停.Send(下單名稱, 最後進場部位.Contracts); } #region 多單指標停損訊號 if (啟用指標停損 == 1 && Bars.Close[0] <= 作空區間) { 下單名稱 = "多單停損"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱 + "_作空區間"); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("最後進場點位", 最後進場部位.Price.ToString()); 設定_輸出集合.Add("作空區間", 作空區間.ToString()); 輸出詳細內容(); } 多停.Send(下單名稱, 最後進場部位.Contracts); } #endregion } // 判斷空單是否需要停損 if (CurrentPosition.Side == EMarketPositionSide.Short && CurrentPosition.OpenTrades.Count > 0) { if (Bars.Close[0] >= 最後進場部位.Price + 停損點數) { 下單名稱 = "空單停損"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱 + "_虧損"); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("最後進場點位", 最後進場部位.Price.ToString()); 設定_輸出集合.Add("停損點位", (最後進場部位.Price + 停損點數).ToString()); 輸出詳細內容(); } 空停.Send(下單名稱, 最後進場部位.Contracts); } #region 空單指標停損訊號 if (啟用指標停損 == 1 && Bars.Close[0] >= 作多區間) { 下單名稱 = "空單停損"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱 + "_作多區間"); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("最後進場點位", 最後進場部位.Price.ToString()); 設定_輸出集合.Add("作多區間", 作多區間.ToString()); 輸出詳細內容(); } 空停.Send(下單名稱, 最後進場部位.Contracts); } #endregion } // 當沖/隔日沖平倉 if (CurrentPosition.Side != EMarketPositionSide.Flat && CurrentPosition.OpenTrades.Count > 0) { // 當沖時於指定出場時間全平 if (濾網_啟用當沖 == 1 && 成交時間 >= 當沖出場時間) { if (CurrentPosition.Side == EMarketPositionSide.Long) { 下單名稱 = "多單當沖全平"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("下單規模", CurrentPosition.OpenLots.ToString()); 輸出詳細內容(); } 多當沖.Send(下單名稱); } if (CurrentPosition.Side == EMarketPositionSide.Short) { 下單名稱 = "空單當沖全平"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("下單規模", CurrentPosition.OpenLots.ToString()); 輸出詳細內容(); } 空當沖.Send(下單名稱); } } else { // 結算當日強制於當沖出場時間平倉 if (結算日集合.ContainsKey(Bars.Time[0].Date) && 成交時間 >= 當沖出場時間) { if (CurrentPosition.Side == EMarketPositionSide.Long) { 下單名稱 = "多單結算日全平"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("下單規模", CurrentPosition.OpenLots.ToString()); 輸出詳細內容(); } 多當沖.Send(下單名稱); } if (CurrentPosition.Side == EMarketPositionSide.Short) { 下單名稱 = "空單結算日全平"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("下單規模", CurrentPosition.OpenLots.ToString()); 輸出詳細內容(); } 空當沖.Send(下單名稱); } } // 隔日沖時於隔日開盤市價平倉 if (!結算日集合.ContainsKey(Bars.Time[0].Date) && 成交時間 >= 濾網_停單時間) { if (CurrentPosition.Side == EMarketPositionSide.Long) { 下單名稱 = "多單隔日沖全平"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("下單規模", CurrentPosition.OpenLots.ToString()); 輸出詳細內容(); } 多隔沖.Send(下單名稱); } if (CurrentPosition.Side == EMarketPositionSide.Short) { 下單名稱 = "空單隔日沖全平"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("下單規模", CurrentPosition.OpenLots.ToString()); 輸出詳細內容(); } 空隔沖.Send(下單名稱); } } } } 前次PositionSide = CurrentPosition.Side; }
protected override void StartCalc() { Data2 = BarsOfData(2); 當沖出場時間 = 132955; 前次PositionSide = EMarketPositionSide.Flat; // 啟用當沖時,若停單時間比 13:30 晚,就提前至 13:30 if (濾網_啟用當沖 == 1) { 濾網_停單時間 = Math.Min(濾網_停單時間, 當沖出場時間); } // 建立結算日資料集合,結算當日強制於當沖出場時間平倉 string 結算日檔案路徑 = 設定_資料檔目錄 + "ExpireDate.TW.csv"; 結算日集合.Clear(); if (File.Exists(結算日檔案路徑)) { string[] 結算日陣列 = File.ReadAllLines(結算日檔案路徑); for (int i = 0; i < 結算日陣列.Length; i++) { 結算日集合.Add(DateTime.ParseExact(結算日陣列[i], "yyyy/MM/dd", CultureInfo.InvariantCulture), true); } } // 建立順勢/逆勢進場週間日集合,只有允許週間日才能進場 順勢進場週間日集合.Clear(); 逆勢進場週間日集合.Clear(); string[] 順勢進場週間日陣列 = 順勢進場週間日.Split(new char[] { ',' }); string[] 逆勢進場週間日陣列 = 逆勢進場週間日.Split(new char[] { ',' }); for (int i = 0; i <= 6; i++) { bool 啟用 = 順勢進場週間日陣列.Count(x => x == i.ToString()) > 0; 順勢進場週間日集合.Add((DayOfWeek)i, 啟用); 啟用 = 逆勢進場週間日陣列.Count(x => x == i.ToString()) > 0; 逆勢進場週間日集合.Add((DayOfWeek)i, 啟用); } // 建立結算隔日進場集合,只有允許月份才能進場 結算隔日進場月份集合.Clear(); string[] 結算隔日進場月份陣列 = 結算隔日進場月份.Split(new char[] { ',' }); for (int i = 1; i <= 12; i++) { bool 啟用 = 結算隔日進場月份陣列.Count(x => x == i.ToString()) > 0; 結算隔日進場月份集合.Add(i, 啟用); } // 計算停損金額在不同商品間換算出的停損點數,如 $3,000 在台指期的停損點數為 15 點 double 每跳動點價值 = Bars.Info.MinMove / Bars.Info.PriceScale * Bars.Info.BigPointValue; if (加減碼_停損金額 > 0) { 停損點數 = 加減碼_停損金額 / 每跳動點價值; } if (加減碼_停損金額 == -1) { //預設15點 停損點數 = 15; // 固定15點 加減碼_停損金額 = (int)(停損點數 * 每跳動點價值); } 設定_輸出集合 = null; 重算日期 = 0; }
protected override void CalcBar() { // 只在 Data2 有資料後才處理分線 if (Data2.CurrentBar <= 1 || Bars.Info.Resolution.Type != EResolution.Minute) { return; } 漲跌.Value = Bars.Close[0] - Bars.Open[0]; 漲跌幅.Value = 100 * ((Bars.Close[0] - Bars.Close[1]) / Bars.Close[1]); 上影線.Value = Bars.High[0] - Math.Max(Bars.Open[0], Bars.Close[0]); 下影線.Value = Math.Min(Bars.Open[0], Bars.Close[0]) - Bars.Low[0]; 實體線.Value = Math.Abs(Bars.Open[0] - Bars.Close[0]); 成交日期 = int.Parse(Bars.Time[0].Date.ToString("yyyyMMdd")); 成交時間 = int.Parse(Bars.BarUpdateTime.ToString("HHmmss")); string m_資料時間 = Bars.BarUpdateTime.ToString("HH:mm:ss"); if (設定_啟用詳細訊息 && 設定_輸出集合 == null) { 設定_輸出集合 = new Dictionary<string, string>(); 設定_輸出集合.Add("輸出記錄", "參數設定"); 設定_輸出集合.Add("策略名稱", 設定_策略名稱); 設定_輸出集合.Add("策略版本", 設定_策略版本); #region 輸出指標策略參數 設定_輸出集合.Add("開始交易時間", 開始交易時間.ToString()); 設定_輸出集合.Add("結束交易時間", 結束交易時間.ToString()); 設定_輸出集合.Add("今日交易獲利次數", 今日交易獲利次數.ToString()); 設定_輸出集合.Add("今日交易連續虧損最多次數", 今日交易連續虧損最多次數.ToString()); 設定_輸出集合.Add("期初狀態", 期初狀態.ToString()); 設定_輸出集合.Add("交易多空1", 交易多空1.ToString()); 設定_輸出集合.Add("間隔秒數1", 間隔秒數1.ToString()); 設定_輸出集合.Add("自設停利點數1", 自設停利點數1.ToString()); 設定_輸出集合.Add("自設停損點數1", 自設停損點數1.ToString()); 設定_輸出集合.Add("下單口數1", 下單口數1.ToString()); 設定_輸出集合.Add("交易多空2", 交易多空2.ToString()); 設定_輸出集合.Add("間隔秒數2", 間隔秒數2.ToString()); 設定_輸出集合.Add("自設停利點數2", 自設停利點數2.ToString()); 設定_輸出集合.Add("自設停損點數2", 自設停損點數2.ToString()); 設定_輸出集合.Add("下單口數2", 下單口數2.ToString()); 設定_輸出集合.Add("交易多空3", 交易多空3.ToString()); 設定_輸出集合.Add("間隔秒數3", 間隔秒數3.ToString()); 設定_輸出集合.Add("自設停利點數3", 自設停利點數3.ToString()); 設定_輸出集合.Add("自設停損點數3", 自設停損點數3.ToString()); 設定_輸出集合.Add("下單口數3", 下單口數3.ToString()); 設定_輸出集合.Add("交易多空4", 交易多空4.ToString()); 設定_輸出集合.Add("間隔秒數4", 間隔秒數4.ToString()); 設定_輸出集合.Add("自設停利點數4", 自設停利點數4.ToString()); 設定_輸出集合.Add("自設停損點數4", 自設停損點數4.ToString()); 設定_輸出集合.Add("下單口數4", 下單口數4.ToString()); #endregion 輸出詳細內容(); } // 換日後需重算關鍵數值 if (Bars.Time[0].Date > Bars.Time[1].Date && 重算日期 < 成交日期) { if (設定_啟用詳細訊息) { 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出記錄", "新交易日"); 設定_輸出集合.Add("原交易日", Bars.Time[1].Date.ToString("yyyy-MM-dd")); 設定_輸出集合.Add("新交易日", Bars.Time[0].Date.ToString("yyyy-MM-dd")); 設定_輸出集合.Add("資料時間", m_資料時間); 輸出詳細內容(); } 重算日期 = 0; } if (重算日期 == 0) { // 如非換日所引起的重算動作就跳出 if (Bars.Time[0].Date < Bars.Time[1].Date) { return; } 昨最高 = Data2.High[0]; 昨最低 = Data2.Low[0]; 昨收盤 = Data2.Close[0]; 今開盤 = Bars.Open[0]; 開高價 = Bars.High[0]; 開低價 = Bars.Low[0]; 開收盤 = Bars.Close[0]; 開漲跌 = Bars.Open[0] - Data2.Close[0]; 開漲跌幅 = 100 * (開漲跌 / Data2.Close[0]); 開盤區間高點 = 0; 開盤區間低點 = int.MaxValue; ATR = AvgTrueRange.AverageTrueRange(this, 14, 0, 2); 當日作多次數 = 0; 當日作空次數 = 0; 前次PositionSide = EMarketPositionSide.Flat; 今最高 = Bars.High[0]; 今最低 = Bars.Low[0]; 今日停單 = false; 週間日 = Bars.Time[0].DayOfWeek; // 資金管理:依模式計算下單規模 double m_可用金額 = InitialCapital + NetProfit; double m_冒險金額 = m_可用金額 * 資金_風險比例; #region 計算指標策略數值1 單次下單次數 = 期初狀態; //換日需重算,需在此填入初始值 今日成功交易次數 = 0;//換日需重算 #endregion 重算日期 = 成交日期; } // 若仍無重算日期記錄就跳出 if (重算日期 == 0) { return; } 今最高 = Math.Max(今最高, Bars.High[0]); 今最低 = Math.Min(今最低, Bars.Low[0]); #region 計算指標策略數值2 #endregion if (CurrentPosition.Side == EMarketPositionSide.Long && 前次PositionSide == EMarketPositionSide.Flat) { if (設定_啟用詳細訊息) { 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 設定_策略名稱 + "_狀態"); 設定_輸出集合.Add("目前狀態", string.Format("失敗:{0} /成功:{1}", 單次下單次數, 今日成功交易次數)); 輸出詳細內容(); } 單次下單次數++; } if (CurrentPosition.Side == EMarketPositionSide.Short && 前次PositionSide == EMarketPositionSide.Flat) { if (設定_啟用詳細訊息) { 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 設定_策略名稱 + "_狀態"); 設定_輸出集合.Add("目前狀態", string.Format("失敗:{0} /成功:{1}", 單次下單次數, 今日成功交易次數)); 輸出詳細內容(); } 單次下單次數++; } if (CurrentPosition.Side == EMarketPositionSide.Flat && 前次PositionSide == EMarketPositionSide.Long) { 上筆成交時間 = int.Parse(Bars.BarUpdateTime.ToString("HHmmss")); if (Is多單獲利) { Is多單獲利 = false; 當日作多次數++; 今日成功交易次數++; 單次下單次數 = 0; //停利重頭開始後繼續玩 if (今日成功交易次數 >= 今日交易獲利次數) { // 獲利了結今日停單 今日停單 = true; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱 + "_停單"); 設定_輸出集合.Add("已達今日成功交易次數", 今日成功交易次數.ToString()); 設定_輸出集合.Add("目前狀態", string.Format("失敗:{0} /成功:{1}", 單次下單次數, 今日成功交易次數)); 輸出詳細內容(); } } } } if (CurrentPosition.Side == EMarketPositionSide.Flat && 前次PositionSide == EMarketPositionSide.Short) { 上筆成交時間 = int.Parse(Bars.BarUpdateTime.ToString("HHmmss")); if (Is空單獲利) { Is空單獲利 = false; 當日作空次數++; 今日成功交易次數++; 單次下單次數 = 0; //停利重頭開始後繼續玩 if (今日成功交易次數 >= 今日交易獲利次數) { // 獲利了結今日停單 今日停單 = true; if (設定_啟用詳細訊息) { 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 設定_策略名稱 + "_停單"); 設定_輸出集合.Add("已達今日成功交易次數", 今日成功交易次數.ToString()); 設定_輸出集合.Add("目前狀態", string.Format("失敗:{0} /成功:{1}", 單次下單次數, 今日成功交易次數)); 輸出詳細內容(); } } } } //--- 下單 ---// if (成交時間 <= 結束交易時間 && CurrentPosition.Side == EMarketPositionSide.Flat && CurrentPosition.OpenTrades.Count == 0 && !今日停單) { //第一次 時間到多單進場 switch (單次下單次數) { case 0: int rt0 = CalDelay((上筆成交時間 == 0) ? 開始交易時間 : 上筆成交時間, 間隔秒數1); if (成交時間 >=rt0) { if (交易多空1 == 1) { 下單名稱 = "做多1"; 多單.Send(下單名稱, 下單口數1); } else { 下單名稱 = "做空1"; 空單.Send(下單名稱, 下單口數1); } } break; case 1: int rt1 = CalDelay(上筆成交時間, 間隔秒數2); if (成交時間 >= rt1) { if (交易多空2 == 1) { 下單名稱 = "做多2"; 多單.Send(下單名稱, 下單口數2); } else { 下單名稱 = "做空2"; 空單.Send(下單名稱, 下單口數2); } } break; case 2: int rt2 = CalDelay(上筆成交時間, 間隔秒數3); if (成交時間 >= rt2) { if (交易多空3 == 1) { 下單名稱 = "做多3"; 多單.Send(下單名稱, 下單口數3); } else { 下單名稱 = "做空3"; 空單.Send(下單名稱, 下單口數3); } } break; case 3: int rt3 = CalDelay(上筆成交時間, 間隔秒數4); if (成交時間 >= rt3) { if (交易多空4 == 1) { 下單名稱 = "做多4"; 多單.Send(下單名稱, 下單口數4); } else { 下單名稱 = "做空4"; 空單.Send(下單名稱, 下單口數4); } } break; default: break; } if (今日交易連續虧損最多次數 <= 單次下單次數) { // 已達連續虧損次數立即停單 今日停單 = true; if (設定_啟用詳細訊息) { 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 設定_策略名稱 + "_停單"); 設定_輸出集合.Add("已達連續虧損次數", 今日交易連續虧損最多次數.ToString()); 設定_輸出集合.Add("目前狀態", string.Format("失敗:{0} /成功:{1}", 單次下單次數, 今日成功交易次數)); 輸出詳細內容(); } } } //--- 平倉 ---// if (CurrentPosition.OpenTrades.Count > 0) { int i停利點數 = 0, i停損點數 = 0; switch (單次下單次數) { case 1: i停利點數 = 自設停利點數1; i停損點數 = 自設停損點數1; break; case 2: i停利點數 = 自設停利點數2; i停損點數 = 自設停損點數2; break; case 3: i停利點數 = 自設停利點數3; i停損點數 = 自設停損點數3; break; case 4: i停利點數 = 自設停利點數4; i停損點數 = 自設停損點數4; break; default: break; } // 判斷多單是否需要停損 if (CurrentPosition.Side == EMarketPositionSide.Long) { if (Bars.Close[0] >= 最後進場部位.Price + i停利點數) { 下單名稱 = "多單停利"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱 + "_獲利"); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("最後進場點位", 最後進場部位.Price.ToString()); 設定_輸出集合.Add("自設停利點數", (最後進場部位.Price + i停利點數).ToString()); 輸出詳細內容(); } 多停.Send(下單名稱); Is多單獲利 = true; } if (Bars.Close[0] <= 最後進場部位.Price - i停損點數) { 下單名稱 = "多單停損"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱 + "_虧損"); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("最後進場點位", 最後進場部位.Price.ToString()); 設定_輸出集合.Add("自設停損點數", (最後進場部位.Price - i停損點數).ToString()); 輸出詳細內容(); } 多停.Send(下單名稱); } } // 判斷空單是否需要停損 if (CurrentPosition.Side == EMarketPositionSide.Short) { if (Bars.Close[0] <= 最後進場部位.Price - i停利點數) { 下單名稱 = "空單停利"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱 + "_獲利"); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("最後進場點位", 最後進場部位.Price.ToString()); 設定_輸出集合.Add("停利點位", (最後進場部位.Price - i停利點數).ToString()); 輸出詳細內容(); } 空停.Send(下單名稱); Is空單獲利 = true; } if (Bars.Close[0] >= 最後進場部位.Price + i停損點數) { 下單名稱 = "空單停損"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱 + "_虧損"); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("最後進場點位", 最後進場部位.Price.ToString()); 設定_輸出集合.Add("停損點位", (最後進場部位.Price + i停損點數).ToString()); 輸出詳細內容(); } 空停.Send(下單名稱); } } } // 當沖/隔日沖平倉 if (CurrentPosition.Side != EMarketPositionSide.Flat && CurrentPosition.OpenTrades.Count > 0) { // 當沖時於指定出場時間全平 if (濾網_啟用當沖 == 1 && 成交時間 >= 當沖出場時間) { if (CurrentPosition.Side == EMarketPositionSide.Long) { 下單名稱 = "多單當沖全平"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("下單規模", CurrentPosition.OpenLots.ToString()); 輸出詳細內容(); } 多當沖.Send(下單名稱); } if (CurrentPosition.Side == EMarketPositionSide.Short) { 下單名稱 = "空單當沖全平"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("下單規模", CurrentPosition.OpenLots.ToString()); 輸出詳細內容(); } 空當沖.Send(下單名稱); } } else { // 結算當日強制於當沖出場時間平倉 if (結算日集合.ContainsKey(Bars.Time[0].Date) && 成交時間 >= 當沖出場時間) { if (CurrentPosition.Side == EMarketPositionSide.Long) { 下單名稱 = "多單結算日全平"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("下單規模", CurrentPosition.OpenLots.ToString()); 輸出詳細內容(); } 多當沖.Send(下單名稱); } if (CurrentPosition.Side == EMarketPositionSide.Short) { 下單名稱 = "空單結算日全平"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("下單規模", CurrentPosition.OpenLots.ToString()); 輸出詳細內容(); } 空當沖.Send(下單名稱); } } // 隔日沖時於隔日開盤市價平倉 if (!結算日集合.ContainsKey(Bars.Time[0].Date) && 成交時間 >= 結束交易時間) { if (CurrentPosition.Side == EMarketPositionSide.Long) { 下單名稱 = "多單隔日沖全平"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("下單規模", CurrentPosition.OpenLots.ToString()); 輸出詳細內容(); } 多隔沖.Send(下單名稱); } if (CurrentPosition.Side == EMarketPositionSide.Short) { 下單名稱 = "空單隔日沖全平"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("下單規模", CurrentPosition.OpenLots.ToString()); 輸出詳細內容(); } 空隔沖.Send(下單名稱); } } } } 前次PositionSide = CurrentPosition.Side; }
protected override void CalcBar() { //if (log.IsDebugEnabled) log.DebugFormat("Time={0}, CurrentBar={1}", Bars.BarUpdateTime.ToString("yyyy/MM/dd HH:mm:ss"), Bars.CurrentBar); // 只在 Data2 有資料後才處理分線 if (Data2.CurrentBar <= 1 || Bars.Info.Resolution.Type != EResolution.Minute) { return; } 漲跌.Value = Bars.Close[0] - Bars.Open[0]; 漲跌幅.Value = 100 * ((Bars.Close[0] - Bars.Close[1]) / Bars.Close[1]); 上影線.Value = Bars.High[0] - Math.Max(Bars.Open[0], Bars.Close[0]); 下影線.Value = Math.Min(Bars.Open[0], Bars.Close[0]) - Bars.Low[0]; 實體線.Value = Math.Abs(Bars.Open[0] - Bars.Close[0]); 成交日期 = int.Parse(Bars.Time[0].Date.ToString("yyyyMMdd")); //成交時間 = int.Parse(Bars.BarUpdateTime.ToString("HHmmss")); //string m_資料時間 = Bars.BarUpdateTime.ToString("HH:mm:ss"); 成交時間 = int.Parse(Bars.Time[0].ToString("HHmmss")); string m_資料時間 = Bars.Time[0].ToString("HH:mm:ss"); if (設定_啟用詳細訊息 && 設定_輸出集合 == null) { 設定_輸出集合 = new Dictionary<string, string>(); 設定_輸出集合.Add("輸出記錄", "參數設定"); 設定_輸出集合.Add("策略名稱", 設定_策略名稱); 設定_輸出集合.Add("策略版本", 設定_策略版本); #region 輸出指標策略參數 設定_輸出集合.Add("啟用指標停損", 啟用指標停損.ToString()); #endregion 設定_輸出集合.Add("啟用順勢進場", 啟用順勢進場.ToString()); 設定_輸出集合.Add("順勢進場週間日", 順勢進場週間日); 設定_輸出集合.Add("啟用逆勢進場", 啟用逆勢進場.ToString()); 設定_輸出集合.Add("逆勢進場週間日", 逆勢進場週間日); 設定_輸出集合.Add("結算隔日進場月份", 結算隔日進場月份); 設定_輸出集合.Add("資金_管理模式", 資金_管理模式.ToString()); 設定_輸出集合.Add("資金_風險比例", 資金_風險比例.ToString()); 設定_輸出集合.Add("資金_基本規模", 資金_基本規模.ToString()); 設定_輸出集合.Add("資金_跳空倍注", 資金_跳空倍注.ToString()); 設定_輸出集合.Add("資金_均多倍注", 資金_均多倍注.ToString()); 設定_輸出集合.Add("資金_均空倍注", 資金_均空倍注.ToString()); 設定_輸出集合.Add("資金_逆勢倍注", 資金_逆勢倍注.ToString()); 設定_輸出集合.Add("濾網_啟用多單", 濾網_啟用多單.ToString()); 設定_輸出集合.Add("濾網_啟用空單", 濾網_啟用空單.ToString()); 設定_輸出集合.Add("濾網_啟用當沖", 濾網_啟用當沖.ToString()); 設定_輸出集合.Add("濾網_開盤區間時間", 濾網_開盤區間時間.ToString()); 設定_輸出集合.Add("濾網_停單時間", 濾網_停單時間.ToString()); 設定_輸出集合.Add("加減碼_停損金額", 加減碼_停損金額.ToString()); 設定_輸出集合.Add("加減碼_停損點數", 停損點數.ToString()); 設定_輸出集合.Add("加減碼_加碼點數", 加減碼_加碼點數.ToString()); 設定_輸出集合.Add("加減碼_加碼次數", 加減碼_加碼次數.ToString()); 輸出詳細內容(); } // 換日後需重算關鍵數值 if (Bars.Time[0].Date > Bars.Time[1].Date && 重算日期 < 成交日期) { if (設定_啟用詳細訊息) { 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出記錄", "新交易日"); 設定_輸出集合.Add("原交易日", Bars.Time[1].Date.ToString("yyyy-MM-dd")); 設定_輸出集合.Add("新交易日", Bars.Time[0].Date.ToString("yyyy-MM-dd")); 設定_輸出集合.Add("資料時間", m_資料時間); 輸出詳細內容(); } 重算日期 = 0; } if (重算日期 == 0) { // 如非換日所引起的重算動作就跳出 if (Bars.Time[0].Date < Bars.Time[1].Date) { return; } 昨最高 = Data2.High[0]; 昨最低 = Data2.Low[0]; 昨收盤 = Data2.Close[0]; 今開盤 = Bars.Open[0]; 開高價 = Bars.High[0]; 開低價 = Bars.Low[0]; 開收盤 = Bars.Close[0]; 開漲跌 = Bars.Open[0] - Data2.Close[0]; 開漲跌幅 = 100 * (開漲跌 / Data2.Close[0]); 開盤區間高點 = 0; 開盤區間低點 = int.MaxValue; ATR = AvgTrueRange.AverageTrueRange(this, 14, 0, 2); 當日作多次數 = 0; 當日作空次數 = 0; 前次PositionSide = EMarketPositionSide.Flat; 今最高 = Bars.High[0]; 今最低 = Bars.Low[0]; 今日停單 = false; 週間日 = Bars.Time[0].DayOfWeek; // 資金管理:依模式計算下單規模 double m_可用金額 = InitialCapital + NetProfit; double m_冒險金額 = m_可用金額 * 資金_風險比例; double m_市場風險 = 0; 下單規模 = 資金_基本規模; switch (資金_管理模式) { case 0: // 固定規模 下單規模 = 資金_基本規模; break; case 1: // 以保證金為基礎計算下單規模 m_市場風險 = Bars.Info.Margin; 下單規模 = Math.Max((int)Math.Floor(m_冒險金額 / m_市場風險), 資金_基本規模); break; case 2: // 以波動度為基礎計算下單規模 m_市場風險 = ATR * Bars.Info.BigPointValue; 下單規模 = Math.Max((int)Math.Floor(m_冒險金額 / m_市場風險), 資金_基本規模); break; } if (資金_跳空倍注 > 0 && 開漲跌幅 >= 資金_跳空倍注) { 下單規模 *= 2; } if (資金_均多倍注 > 0 && 開收盤 > Data2.Close.Average(資金_均多倍注)) { 下單規模 *= 2; } if (資金_均空倍注 > 0 && 開收盤 < Data2.Close.Average(資金_均空倍注)) { 下單規模 *= 2; } #region 計算指標策略數值1 // 原版 CDP 公式 m_CDP = (昨最高 + 昨最低 + 昨收盤 * 2) * 0.25; m_AH = m_CDP + (昨最高 - 昨最低); m_NH = m_CDP * 2 - 昨最低; m_NL = m_CDP * 2 - 昨最高; m_AL = m_CDP - (昨最高 - 昨最低); // 老狼改良版,各線距離減半,績效將比原版成長數倍 m_AH = (m_AH + m_NH) / 2; m_NH = (m_NH + m_CDP) / 2; m_AL = (m_AL + m_NL) / 2; m_NL = (m_NL + m_CDP) / 2; // 若 AH - AL 小於商品的 0.2% 幅度,今日就停單 if (m_AH - m_AL < 今開盤 * 0.002) { 今日停單 = true; } if (設定_啟用詳細訊息) { 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出記錄", "指標數值"); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("AH", m_AH.ToString("N2")); 設定_輸出集合.Add("NH", m_NH.ToString("N2")); 設定_輸出集合.Add("CDP", m_CDP.ToString("N2")); 設定_輸出集合.Add("NL", m_NL.ToString("N2")); 設定_輸出集合.Add("AL", m_AL.ToString("N2")); 輸出詳細內容(); } #endregion // 本交易日開倉,但不在進場月份中就停單 if (結算日集合.ContainsKey(Bars.Time[1].Date) && !結算隔日進場月份集合[Bars.Time[0].Date.Month]) { 今日停單 = true; } if (設定_啟用詳細訊息 && 今日停單) { 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出記錄", "今日停單"); 設定_輸出集合.Add("日期", Bars.Time[0].ToString("yyyy-MM-dd")); 設定_輸出集合.Add("停單", 今日停單.ToString()); 輸出詳細內容(); } if (設定_啟用詳細訊息) { 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出記錄", "下單規模"); 設定_輸出集合.Add("口數", 下單規模.ToString()); 輸出詳細內容(); } 重算日期 = 成交日期; } // 若仍無重算日期記錄就跳出 if (重算日期 == 0) { return; } 今最高 = Math.Max(今最高, Bars.High[0]); 今最低 = Math.Min(今最低, Bars.Low[0]); #region 計算指標策略數值2 #endregion // 開盤區間內只記錄高低價,不判斷訊號 if (濾網_開盤區間時間 > 0 && 成交時間 <= 濾網_開盤區間時間) { 開盤區間高點 = Math.Max(開盤區間高點, Bars.High[0]); 開盤區間低點 = Math.Min(開盤區間低點, Bars.Low[0]); if (設定_啟用詳細訊息) { if (m_資料時間 == "09:05:00") { 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出記錄", "計算"); 設定_輸出集合.Add("區間高點", 開盤區間高點.ToString()); 設定_輸出集合.Add("AH", m_AH.ToString("N2")); if (逆勢進場週間日集合[週間日]) { string 判斷 = " (False)"; if (開低價 <= m_AL) { 判斷 = " (True)"; } 設定_輸出集合.Add("開低價", 開低價.ToString()); 設定_輸出集合.Add("AL" + 判斷, m_AL.ToString("N2")); } 設定_輸出集合.Add("資料時間", m_資料時間); 輸出詳細內容(); } } return; } if (CurrentPosition.Side == EMarketPositionSide.Long && 前次PositionSide == EMarketPositionSide.Flat) { 當日作多次數++; } if (CurrentPosition.Side == EMarketPositionSide.Short && 前次PositionSide == EMarketPositionSide.Flat) { 當日作空次數++; } // 判斷順勢進場新單訊號 if (啟用順勢進場 == 1) { #region 順勢進場新單訊號 if (CurrentPosition.Side == EMarketPositionSide.Flat && CurrentPosition.OpenTrades.Count == 0 && 成交時間 <= 濾網_停單時間 && !今日停單) { if (濾網_啟用多單 == 1 && 當日作多次數 == 0 && Bars.Close[0] >= 開盤區間高點 && Bars.Close[0] >= m_AH && 順勢進場週間日集合[週間日]) { 下單名稱 = "突破作多"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_AH" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("AH", m_AH.ToString()); 設定_輸出集合.Add("區間高點", 開盤區間高點.ToString()); 設定_輸出集合.Add("今日高點", 今最高.ToString()); 設定_輸出集合.Add("下單規模", 下單規模.ToString()); 輸出詳細內容(); } 多單.Send(下單名稱, 下單規模); } if (濾網_啟用空單 == 1 && 當日作空次數 == 0 && Bars.Close[0] <= m_AL && Bars.Close[0] <= 開盤區間低點 && 順勢進場週間日集合[週間日]) { 下單名稱 = "跌破作空"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_AL" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("AL", m_AL.ToString()); 設定_輸出集合.Add("區間低點", 開盤區間低點.ToString()); 設定_輸出集合.Add("今日低點", 今最低.ToString()); 設定_輸出集合.Add("下單規模", 下單規模.ToString()); 輸出詳細內容(); } 空單.Send(下單名稱, 下單規模); } } #endregion } // 判斷逆勢進場新單訊號 if (啟用逆勢進場 == 1) { #region 逆勢進場新單訊號 if (CurrentPosition.Side == EMarketPositionSide.Flat && CurrentPosition.OpenTrades.Count == 0 && 成交時間 <= 濾網_停單時間 && !今日停單) { if (濾網_啟用多單 == 1 && 當日作多次數 == 0 && Bars.Close[0] >= m_AL && (m_AL - 開低價 >= 0) && 逆勢進場週間日集合[週間日]) { 下單名稱 = "反彈作多"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_AL" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("AL", m_AL.ToString()); 設定_輸出集合.Add("開低價", 開低價.ToString()); 設定_輸出集合.Add("下單規模", ((資金_逆勢倍注 == 1) ? 下單規模 * 2 : 下單規模).ToString()); 輸出詳細內容(); } 多單.Send(下單名稱, (資金_逆勢倍注 == 1) ? 下單規模 * 2 : 下單規模); } // 穿頭殺回作空 if (濾網_啟用空單 == 1 && 當日作空次數 == 0 && Bars.Close[0] <= m_AH && (開高價 - m_AH >= 0) && 逆勢進場週間日集合[週間日]) { 下單名稱 = "殺回作空"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_AH" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("AH", m_AH.ToString()); 設定_輸出集合.Add("開高價", 開高價.ToString()); 設定_輸出集合.Add("下單規模", ((資金_逆勢倍注 == 1) ? 下單規模 * 2 : 下單規模).ToString()); 輸出詳細內容(); } 空單.Send(下單名稱, (資金_逆勢倍注 == 1) ? 下單規模 * 2 : 下單規模); } } #endregion } // 判斷多單是否需要加碼 if (CurrentPosition.Side == EMarketPositionSide.Long && CurrentPosition.OpenTrades.Count <= 加減碼_加碼次數) { if (Bars.Close[0] >= 最後進場部位.Price + 加減碼_加碼點數) { 下單名稱 = "多單加碼"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("最後進場點位", 最後進場部位.Price.ToString()); 設定_輸出集合.Add("加碼點位", (最後進場部位.Price + 加減碼_加碼點數).ToString()); 設定_輸出集合.Add("下單規模", ((資金_逆勢倍注 == 1) ? 下單規模 * 2 : 下單規模).ToString()); 輸出詳細內容(); } 多單.Send(下單名稱, 最後進場部位.Contracts); } } // 判斷空單是否需要加碼 if (CurrentPosition.Side == EMarketPositionSide.Short && CurrentPosition.OpenTrades.Count <= 加減碼_加碼次數) { if (Bars.Close[0] <= 最後進場部位.Price - 加減碼_加碼點數) { 下單名稱 = "空單加碼"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("最後進場點位", 最後進場部位.Price.ToString()); 設定_輸出集合.Add("加碼點位", (最後進場部位.Price - 加減碼_加碼點數).ToString()); 設定_輸出集合.Add("下單規模", ((資金_逆勢倍注 == 1) ? 下單規模 * 2 : 下單規模).ToString()); 輸出詳細內容(); } 空單.Send(下單名稱, 最後進場部位.Contracts); } } // 判斷多單是否需要停損 if (CurrentPosition.Side == EMarketPositionSide.Long && CurrentPosition.OpenTrades.Count > 0) { if (Bars.Close[0] <= 最後進場部位.Price - 停損點數) { 下單名稱 = "多單停損"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱 + "_虧損"); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("最後進場點位", 最後進場部位.Price.ToString()); 設定_輸出集合.Add("停損點位", (最後進場部位.Price - 停損點數).ToString()); 輸出詳細內容(); } 多停.Send(下單名稱, 最後進場部位.Contracts); } #region 多單指標停損訊號 if (啟用指標停損 == 1 && Bars.Close[0] <= m_NH) { 下單名稱 = "多單停損"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱 + "_NH"); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("最後進場點位", 最後進場部位.Price.ToString()); 設定_輸出集合.Add("NH", m_NH.ToString()); 輸出詳細內容(); } 多停.Send(下單名稱, 最後進場部位.Contracts); } #endregion } // 判斷空單是否需要停損 if (CurrentPosition.Side == EMarketPositionSide.Short && CurrentPosition.OpenTrades.Count > 0) { if (Bars.Close[0] >= 最後進場部位.Price + 停損點數) { 下單名稱 = "空單停損"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱 + "_虧損"); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("最後進場點位", 最後進場部位.Price.ToString()); 設定_輸出集合.Add("停損點位", (最後進場部位.Price + 停損點數).ToString()); 輸出詳細內容(); } 空停.Send(下單名稱, 最後進場部位.Contracts); } #region 空單指標停損訊號 if (啟用指標停損 == 1 && Bars.Close[0] >= m_NL) { 下單名稱 = "空單停損"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱 + "_NL"); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("最後進場點位", 最後進場部位.Price.ToString()); 設定_輸出集合.Add("NL", m_NL.ToString()); 輸出詳細內容(); } 空停.Send(下單名稱, 最後進場部位.Contracts); } #endregion } // 當沖/隔日沖平倉 if (CurrentPosition.Side != EMarketPositionSide.Flat && CurrentPosition.OpenTrades.Count > 0) { // 當沖時於指定出場時間全平 if (濾網_啟用當沖 == 1 && 成交時間 >= 當沖出場時間) { if (CurrentPosition.Side == EMarketPositionSide.Long) { 下單名稱 = "多單當沖全平"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("下單規模", CurrentPosition.OpenLots.ToString()); 輸出詳細內容(); } 多當沖.Send(下單名稱); } if (CurrentPosition.Side == EMarketPositionSide.Short) { 下單名稱 = "空單當沖全平"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("下單規模", CurrentPosition.OpenLots.ToString()); 輸出詳細內容(); } 空當沖.Send(下單名稱); } } else { // 結算當日強制於當沖出場時間平倉 if (結算日集合.ContainsKey(Bars.Time[0].Date) && 成交時間 >= 當沖出場時間) { if (CurrentPosition.Side == EMarketPositionSide.Long) { 下單名稱 = "多單結算日全平"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("下單規模", CurrentPosition.OpenLots.ToString()); 輸出詳細內容(); } 多當沖.Send(下單名稱); } if (CurrentPosition.Side == EMarketPositionSide.Short) { 下單名稱 = "空單結算日全平"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("下單規模", CurrentPosition.OpenLots.ToString()); 輸出詳細內容(); } 空當沖.Send(下單名稱); } } // 隔日沖時於隔日開盤市價平倉 if (!結算日集合.ContainsKey(Bars.Time[0].Date) && 成交時間 >= 濾網_停單時間) { if (CurrentPosition.Side == EMarketPositionSide.Long) { 下單名稱 = "多單隔日沖全平"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("下單規模", CurrentPosition.OpenLots.ToString()); 輸出詳細內容(); } 多隔沖.Send(下單名稱); } if (CurrentPosition.Side == EMarketPositionSide.Short) { 下單名稱 = "空單隔日沖全平"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("輸出下單", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("下單規模", CurrentPosition.OpenLots.ToString()); 輸出詳細內容(); } 空隔沖.Send(下單名稱); } } } } 前次PositionSide = CurrentPosition.Side; }
protected override void CalcBar() { 成交日期 = int.Parse(Bars.Time[0].Date.ToString("yyyyMMdd")); 成交時間 = int.Parse(Bars.BarUpdateTime.ToString("HHmmss")); string m_資料時間 = Bars.Time[0].ToString("HH:mm:ss"); if (設定_啟用詳細訊息 && 設定_輸出集合 == null) { 設定_輸出集合 = new Dictionary<string, string>(); 設定_輸出集合.Add("OutputLogs", "參數設定"); 設定_輸出集合.Add("策略名稱", 設定_策略名稱); 設定_輸出集合.Add("策略版本", 設定_策略版本); 設定_輸出集合.Add("開始交易時間", Convert時間(開始交易時間)); 設定_輸出集合.Add("結束交易時間", Convert時間(結束交易時間)); 設定_輸出集合.Add("當沖全平時間", Convert時間(當沖全平時間)); 設定_輸出集合.Add("下單口數", 下單口數.ToString()); 設定_輸出集合.Add("停損點數", 停損點數.ToString()); 設定_輸出集合.Add("停利點數", 停利點數.ToString()); 輸出詳細內容(); } // 換日後需重算關鍵數值 if (Bars.Time[0].Date > Bars.Time[1].Date && 重算日期 < 成交日期) { if (設定_啟用詳細訊息) { 設定_輸出集合.Clear(); 設定_輸出集合.Add("OutputLogs", "新交易日"); 設定_輸出集合.Add("原交易日", Bars.Time[1].Date.ToString("yyyy-MM-dd")); 設定_輸出集合.Add("新交易日", Bars.Time[0].Date.ToString("yyyy-MM-dd")); 設定_輸出集合.Add("資料時間", m_資料時間); 輸出詳細內容(); } 重算日期 = 0; } if (重算日期 == 0) { // 如非換日所引起的重算動作就跳出 if (Bars.Time[0].Date < Bars.Time[1].Date) { return; } __d突破價 = 0; __dMaxPrice = 0; 當日作多次數 = 0; 當日作空次數 = 0; 前次PositionSide = EMarketPositionSide.Flat; 重算日期 = 成交日期; } // 若仍無重算日期記錄就跳出 if (重算日期 == 0) { return; } if (CurrentPosition.Side == EMarketPositionSide.Long && 前次PositionSide == EMarketPositionSide.Flat) { 當日作多次數++; } if (CurrentPosition.Side == EMarketPositionSide.Short && 前次PositionSide == EMarketPositionSide.Flat) { 當日作空次數++; } if (CurrentPosition.Side == EMarketPositionSide.Flat && 前次PositionSide == EMarketPositionSide.Long) { //多單平倉 } double dOpen = Bars.Open[0]; double dHigh = Bars.High[0]; double dLow = Bars.Low[0]; double dClose = Bars.Close[0]; double dVolume = Bars.Volume[0]; //Console.WriteLine(string.Format("量_({0}){1}", Convert時間(成交時間), dVolume)); //--- 觸發多單進場 (目前版本無倉且符合條件才下單) if (CurrentPosition.Side == EMarketPositionSide.Flat && CurrentPosition.OpenTrades.Count == 0) { //無倉狀態 if (成交時間 >= 開始交易時間 && 成交時間 <= 結束交易時間) { // 判斷突破條件:當該跟黑K 且 量>1000 且 當跟最低價< 前15跟最低價最小值 if (dVolume > 1000) { //量>1000,回測系統沒有一分K的量 //Console.WriteLine(string.Format("量大1000_({0}){1}>1000", Convert時間(成交時間), dVolume)); double dLow_ = Bars.Low[1]; if (成交時間 > 90100) { //取前15跟最低價 for (int i = 2; i <= 15; i++) { dLow_ = Math.Min(dLow_, Bars.Low[i]); } } double dLow15 = dLow_;// Bars.Low.Lowest(15); //double dLow15 = Bars.Low.Lowest(15); if (dLow <= dLow15) { //Console.WriteLine(string.Format("跌破前15跟新低_({0}){1}<{2}", Convert時間(成交時間), dLow, dLow15)); if (dClose < dOpen) { // 黑K //Console.WriteLine(string.Format("黑K_({0}){1}<{2}", Convert時間(成交時間), dClose, dOpen)); __d突破價 = dHigh; 下單名稱 = "偵測突破"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("OutputLogs", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("突破價", __d突破價.ToString()); 輸出詳細內容(); } } } } if (dClose > __d突破價 && __d突破價 > 0) { 下單名稱 = "突破作多"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("OutputOrders", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("突破價", __d突破價.ToString()); 設定_輸出集合.Add("下單口數", 下單口數.ToString()); 輸出詳細內容(); } __d突破價 = 0; //進場後後歸零,重新找新的 多單.Send(下單名稱, 下單口數); } } } //--- 多單平倉,過下單時間後也要執行平倉動作 if (CurrentPosition.Side == EMarketPositionSide.Long) { double dOpenPrice = 最後進場部位.Price; // --- 1. 多單停利 if (Bars.Close[0] >= dOpenPrice + 停利點數) { //__d突破價 = 0; // 1.停利須歸零 下單名稱 = "多單停利"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("OutputOrders", 下單名稱 + "_停利"); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("最後進場點位", 最後進場部位.Price.ToString()); 設定_輸出集合.Add("停利點位", (最後進場部位.Price + 停利點數).ToString()); 輸出詳細內容(); } 多停.Send(下單名稱); } // --- 2. 移動停損 if (__dMaxPrice == 0) { //成交後初值須填入 __dMaxPrice = dOpenPrice; } if (dClose > dOpenPrice && dClose > __dMaxPrice) { __dMaxPrice = dClose; //更新買進後最高價 } else { double dDiff = __dMaxPrice - dClose; if (dDiff >= 停損點數) { //移動停損 //__d突破價 = 0; // 2.停損須歸零 下單名稱 = "移動停損"; if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("OutputOrders", 下單名稱 + "_多單"); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("最後進場點位", 最後進場部位.Price.ToString()); 設定_輸出集合.Add("高點", __dMaxPrice.ToString()); 設定_輸出集合.Add("平倉點位", (最後進場部位.Price - 停損點數).ToString()); 輸出詳細內容(); } __dMaxPrice = 0; 多停.Send(下單名稱); } } // --- 3.時間到時平倉 if (成交時間 >= 當沖全平時間) { //全部平倉 下單名稱 = "多單當沖全平"; //__d突破價 = 0; // 3.平倉須歸零 if (設定_啟用詳細訊息) { 下單名稱 = 設定_策略名稱 + "_" + 下單名稱; 設定_輸出集合.Clear(); 設定_輸出集合.Add("OutputOrders", 下單名稱); 設定_輸出集合.Add("時間", m_資料時間); 設定_輸出集合.Add("成交價", Bars.Close[0].ToString()); 設定_輸出集合.Add("平倉口數", CurrentPosition.OpenLots.ToString()); 輸出詳細內容(); } 多停.Send(下單名稱); } } 前次PositionSide = CurrentPosition.Side; }
protected override void StartCalc() { 前次PositionSide = EMarketPositionSide.Flat; 重算日期 = 0; }