/// <summary> /// Initializes a new instance of the TradeHelper class. /// </summary> /// <param name="tradeSystem">The trading system to use.</param> public TradeHelper(TradeSystem tradeSystem) { this.tradeSystem = tradeSystem; this.Capital = tradeSystem.FinancialSettings.InitialCapital; this.currentTrade = new Trade(this.tradeSystem.FinancialSettings.MaxDrawdown, this.tradeSystem.FinancialSettings.DollarsPerPoint, this.tradeSystem.FinancialSettings.RoundTripCommission, this.Capital); }
public Trades EvalTrades(TradeSystem tradeSystem, TradeCondition buyCondition, TradeCondition sellCondition, double stopOutValue, bool log = false) { object[] logRowData = null; if (log) { int logIndex = -1; this.LogTables = new DataTable("LogTable"); this.LogTables.Columns.Add("Date"); this.LogTables.Columns.Add("Time"); this.LogTables.Columns.Add("Open"); this.LogTables.Columns.Add("High"); this.LogTables.Columns.Add("Low"); this.LogTables.Columns.Add("Close"); this.LogTables.Columns.Add("Volume"); this.LogTables.Columns.Add("StopOut"); this.LogTables.Columns.Add("Buy Signal"); this.LogTables.Columns.Add("Sell Signal"); TradeRule tr; for (int i = 0; i < buyCondition.TradeRules.Count; i++) { tr = buyCondition.TradeRules[i]; logIndex++; this.LogTables.Columns.Add(string.Format("{0} {1} {2} -BR{3}", tr.IndicatorName1, tr.CompareType.ToString(), tr.IndicatorName2, logIndex)); this.LogTables.Columns.Add(string.Format("Result -BR{0}", logIndex)); this.LogTables.Columns.Add(string.Format("JoinType -BR{0}", logIndex)); } logIndex = 0; for (int i = 0; i < sellCondition.TradeRules.Count; i++) { tr = sellCondition.TradeRules[i]; logIndex++; this.LogTables.Columns.Add(string.Format("{0} {1} {2} -SR{3}", tr.IndicatorName1, tr.CompareType.ToString(), tr.IndicatorName2, logIndex)); this.LogTables.Columns.Add(string.Format("Result -SR{0}", logIndex)); this.LogTables.Columns.Add(string.Format("JoinType -SR{0}", logIndex)); } logRowData = GetEmptyArray(this.LogTables.Columns.Count); } bool stopout = stopOutValue != double.MaxValue; DateTime startDate = tradeSystem.StartDate; DateTime endDate = tradeSystem.EndDate; TradeType? tradeType = null; if(tradeSystem.Longs && ! tradeSystem.Shorts) { tradeType = TradeType.longTrade; } else if (!tradeSystem.Longs && tradeSystem.Shorts) { tradeType = TradeType.shortTrade; } this.Winners = 0; this.Losers = 0; this.StopOuts = 0; this.Trades = new Trades(); this.Capital = tradeSystem.FinancialSettings.InitialCapital; bool[] buys = GetValues(buyCondition); bool[] sells = GetValues(sellCondition); List<int> endOfDaysIndexes = this.IndicatorLibraryAdapter.EndOfDayIndex; bool buySignal; bool sellSignal; bool longEntered = false; bool shortEntered = false; double maxDrawDown = tradeSystem.FinancialSettings.MaxDrawdown; double dollarsPerPoint = tradeSystem.FinancialSettings.DollarsPerPoint; double roundTripCommision = tradeSystem.FinancialSettings.RoundTripCommission; double currentCapital = tradeSystem.FinancialSettings.InitialCapital; double equityPerContract = tradeSystem.FinancialSettings.EquityPerContract; int maxContracts = tradeSystem.FinancialSettings.MaxContracts; int counter = 0; Trade trade = null; StockPoint stockPoint = null; DateTime currentDateTime; #region Enter/Exit and Log Trade Func int stopOutCounter = 0; Action EnterLog = () => { StockPoint point = StockPoints[counter]; logRowData[0] = point.Date; logRowData[1] = point.Time; logRowData[2] = point.Open.ToString("0.00"); logRowData[3] = point.High.ToString("0.00"); logRowData[4] = point.Low.ToString("0.00"); logRowData[5] = point.Close.ToString("0.00"); logRowData[6] = point.Volume.ToString(); if (stopOutCounter != this.StopOuts) { stopOutCounter = this.StopOuts; this.LogTables.Rows[this.LogTables.Rows.Count - 1][7] = "1"; } logRowData[7] = "0"; if (endOfDaysIndexes.Contains(counter)) { logRowData[8] = "end of day"; logRowData[9] = "end of day"; } else { logRowData[8] = buys[counter] ? "1" : "0"; logRowData[9] = sells[counter] ? "1" : "0"; } int logIndex = 9; TradeRule tr; double[] evalData; for (int i = 0; i < buyCondition.TradeRules.Count; i++) { tr = buyCondition.TradeRules[i]; evalData = this.Data[tr.Name]; logRowData[++logIndex] = string.Format("{0} {1} {2}", this.IndicatorLibraryAdapter.Data[tr.IndicatorName1][counter].ToString(), tr.CompareType.ToString(), tr.IndicatorName2.Contains("#") ? tr.IndicatorName2.Replace("#", "") : Convert.ToString(this.IndicatorLibraryAdapter.Data[tr.IndicatorName2][counter])); logRowData[++logIndex] = evalData[counter].ToString("0"); logRowData[++logIndex] = buyCondition.RuleJoinTypes[i].ToString(); } for (int i = 0; i < sellCondition.TradeRules.Count; i++) { tr = sellCondition.TradeRules[i]; evalData = this.Data[tr.Name]; logRowData[++logIndex] = string.Format("{0} {1} {2}", this.IndicatorLibraryAdapter.Data[tr.IndicatorName1][counter], tr.CompareType.ToString(), tr.IndicatorName2.Contains("#") ? tr.IndicatorName2.Replace("#", "") : Convert.ToString(this.IndicatorLibraryAdapter.Data[tr.IndicatorName2][counter])); logRowData[++logIndex] = evalData[counter].ToString("0"); logRowData[++logIndex] = sellCondition.RuleJoinTypes[i].ToString(); } this.LogTables.Rows.Add(logRowData); logRowData = GetEmptyArray(this.LogTables.Columns.Count); }; // returns if entry point is the last point Action<TradeType> EnterTrade = (entryTradeType) => { longEntered = entryTradeType == TradeType.longTrade; shortEntered = entryTradeType == TradeType.shortTrade; trade = new Trade(maxDrawDown, dollarsPerPoint, roundTripCommision, currentCapital); trade.Enter(this.StockPoints[counter + 1], entryTradeType, Math.Min((int)(currentCapital / equityPerContract), maxContracts)); }; // returns if the needs to exit Func<bool, int, int, bool> ExitTrade = (isStopped, indexIncreamentvalue, decrement) => { trade.Exit(this.StockPoints[counter + indexIncreamentvalue], decrement, isStopped); currentCapital = Math.Round(Math.Max(currentCapital + trade.Profit, 0D), 2); if (trade.Profit > 0) { this.Winners++; } else if (trade.Profit < 0) { this.Losers++; } if(isStopped) { this.StopOuts++; } Trades.Add(trade); longEntered = false; shortEntered = false; return currentCapital < equityPerContract; }; #endregion Enter/Exit Trade Func for (counter = 0; counter < this.StockPoints.Count(); counter++) { if (this.Cancelled) { this.Cancelled = false; return Trades; } buySignal = buys[counter]; sellSignal = sells[counter]; stockPoint = StockPoints[counter]; currentDateTime = stockPoint.PointDateTime; if (currentDateTime >= endDate) { if (longEntered || shortEntered) { ExitTrade(false, 0, 0); } break; } if (currentDateTime < startDate) { continue; } if (log) EnterLog(); if (currentDateTime.AddMinutes(30).Hour >= 9) { if (longEntered || shortEntered) { // exit end of day, if long/short entered or beyond specified date if (endOfDaysIndexes.Contains(counter)) { if (ExitTrade(false, 0, 0)) break; } // exit trade logic else if ((longEntered && sellSignal) || (shortEntered && buySignal)) { if (ExitTrade(false, 1, 5)) break; } //stopout else if (stopout && ((trade.TradeType == TradeType.longTrade && trade.EntryPrice - stockPoint.Low >= stopOutValue) || (trade.TradeType == TradeType.shortTrade && stockPoint.High - trade.EntryPrice >= stopOutValue))) { if (ExitTrade(true, 1, 5)) break; } continue; } // enter trade logic if (!(longEntered || shortEntered || endOfDaysIndexes.Contains(counter))) { if (buySignal && (tradeType == null || tradeType.Value == TradeType.longTrade)) { EnterTrade(TradeType.longTrade); } else if (sellSignal && (tradeType == null || tradeType.Value == TradeType.shortTrade)) { EnterTrade(TradeType.shortTrade); } } } } return Trades; }