public StrategyTesterResult[,] Run() { #region Initialize variables StrategyTesterResult[,] resultset = new StrategyTesterResult[Basket.Length, 19]; List <TradeInfo>[,] TRADES = new List <TradeInfo> [Basket.Length, 19]; int[,] OpenTradePositionIndex = new int[Basket.Length, 19]; #endregion #region Fill up initial results for (int i = 0; i < Basket.Length; i++) { for (int j = 0; j < 19; j++) { resultset[i, j] = new StrategyTesterResult(); resultset[i, j].Basket = Basket; resultset[i, j].window = Window; resultset[i, j].maximum_open_positions = MaxOpenPositions; resultset[i, j].final_balance = InitialDeposit; resultset[i, j].balance_history = new List <double>(); resultset[i, j].balance_history.Add(InitialDeposit); resultset[i, j].transactionCost = TransactionCost; resultset[i, j].initialDeposit = InitialDeposit; resultset[i, j].leverage = Leverage; TRADES[i, j] = new List <TradeInfo>(); } } #endregion for (int i = Window - 1; i < n_data; i++) { #region Regression double[,] xy = new double[Window, Basket.Length]; for (int j = 0; j < Window; j++) { for (int k = 0; k < Basket.Length; k++) { xy[j, k] = Price[k, i - j]; } } double[] x = new double[Basket.Length]; for (int j = 0; j < Basket.Length; j++) { x[j] = Price[j, i]; } double[][] W = new double[Basket.Length][]; for (int j = 0; j < Basket.Length; j++) { W[j] = LinearRegression.Build(xy, j); } #endregion for (int j = 0; j < Basket.Length; j++) { double[] w = W[j]; #region Calculate SD double sum = 0; double sd = 0; double mean = 0; double upperBand, lowerBand, deviation; for (int k = 1; k < Window; k++) { sum += LinearRegression.Predict(Price, i - k, w); } mean = sum / Window; sum = 0; for (int k = 1; k < Window; k++) { double val = LinearRegression.Predict(Price, i - k, w); sum += ((val - mean) * (val - mean)); } sd = Math.Sqrt(sum / Window); #endregion for (int k = 0; k < 19; k++) { List <TradeInfo> Trades = TRADES[j, k]; StrategyTesterResult result = resultset[j, k]; result.bandwidth = (k + 1) * 0.25; #region Calculate bands deviation = (k + 1) * 0.25 * sd; upperBand = mean + deviation; lowerBand = mean - deviation; #endregion #region Locate current and previous positions int current_position = 0; int previous_position = 0; double current_val = LinearRegression.Predict(Price, i, w); double previous_val = LinearRegression.Predict(Price, i - 1, w); if (current_val >= upperBand) { current_position = 1; } else if (current_val < upperBand && current_val > mean) { current_position = 2; } else if (current_val <= mean && current_val > lowerBand) { current_position = 3; } else { current_position = 4; } if (previous_val >= upperBand) { previous_position = 1; } else if (previous_val < upperBand && previous_val > mean) { previous_position = 2; } else if (previous_val <= mean && previous_val > lowerBand) { previous_position = 3; } else { previous_position = 4; } #endregion #region Trades //######################### Close open trades ##################################################### foreach (TradeInfo trade in Trades) { double v = LinearRegression.Predict(Price, i, trade.Coefficients); if (trade.Action == 1) { #region Check Buy Order if (v >= trade.TP) { //TP is hit. Winner :) trade.IsClosed = true; trade.close_index = i; result.tradedurations.Add(i - trade.open_index); double estimatepips = 0; double profit = GetProfit(trade, out estimatepips); updateResults(result, 1, profit, estimatepips); if (profit < 0) { result.total_TP_mismatch++; } } else if (v <= trade.SL) { //SL is hit. Loser :( trade.IsClosed = true; trade.close_index = i; result.tradedurations.Add(i - trade.open_index); double estimatepips = 0; double profit = GetProfit(trade, out estimatepips); updateResults(result, 1, profit, estimatepips); if (profit > 0) { result.total_SL_mismatch++; } } #endregion } else { #region Check Sell Order if (v <= trade.TP) { //TP is hit. Winner :) trade.IsClosed = true; trade.close_index = i; result.tradedurations.Add(i - trade.open_index); double estimatepips = 0; double profit = GetProfit(trade, out estimatepips); updateResults(result, 1, profit, estimatepips); if (profit < 0) { result.total_TP_mismatch++; } } else if (v >= trade.SL) { //SL is hit. Loser :( trade.IsClosed = true; trade.close_index = i; result.tradedurations.Add(i - trade.open_index); double estimatepips = 0; double profit = GetProfit(trade, out estimatepips); updateResults(result, 1, profit, estimatepips); if (profit > 0) { result.total_SL_mismatch++; } } #endregion } } Trades.RemoveAll(trade => trade.IsClosed); //################################## Open trade signals ###################################### if (Trades.Count < MaxOpenPositions) { if (previous_position == 1 && current_position == 2) { //Sell order #region Execute sell order double[] c = LinearRegression.NormalizeWeights(w, x, InversionDirection); int[] lotsizes = RiskManager.getTradeSizes(c, result.final_balance, Leverage); if (lotsizes != null) { TradeInfo trade = new TradeInfo(); trade.Action = -1; trade.Coefficients = w; trade.IsClosed = false; trade.TP = mean; trade.SL = mean + 2 * deviation; trade.TradeSizes = lotsizes; trade.open_index = i; trade.IsClosed = false; Trades.Add(trade); result.tradesizes.Add(LinearRegression.TotalNormalizedWeights(w, x, InversionDirection)); } else { result.total_reject_trades++; } #endregion } else if (previous_position == 4 & current_position == 3) { //Buy order #region Execute buy order double[] c = LinearRegression.NormalizeWeights(w, x, InversionDirection); int[] lotsizes = RiskManager.getTradeSizes(c, result.final_balance, Leverage); if (lotsizes != null) { TradeInfo trade = new TradeInfo(); trade.Action = -1; trade.Coefficients = w; trade.IsClosed = false; trade.TP = mean; trade.SL = mean - 2 * deviation; trade.TradeSizes = lotsizes; trade.open_index = i; trade.IsClosed = false; Trades.Add(trade); result.tradesizes.Add(LinearRegression.TotalNormalizedWeights(w, x, InversionDirection)); } else { result.total_reject_trades++; } #endregion } } //##################################################################################### #endregion } } } #region Post Mortem for (int i = 0; i < Basket.Length; i++) { for (int j = 0; j < 19; j++) { resultset[i, j].postMortem(); resultset[i, j].balance_history = null; resultset[i, j].tradesizes = null; resultset[i, j].tradedurations = null; } } #endregion return(resultset); }
public StrategyTesterResult Run() { #region Initialize variables StrategyTesterResult result = new StrategyTesterResult(); double[] TS = new double[n_data - Window + 1]; double[,] Weights = new double[n_data - Window + 1, Basket.Length + 1]; List <string> WeightNames = new List <string>(Basket); WeightNames.Add("Intercept"); List <string> notes = new List <string>(); List <TradeInfo> Trades = new List <TradeInfo>(); List <double[]> StandardizedWeights = new List <double[]>(); List <double[]> NormalizedWeights = new List <double[]>(); List <int[]> TradeSizes = new List <int[]>(); #endregion #region Fill up initial results result.Basket = Basket; result.window = Window; result.bandwidth = Bandwidth; result.transactionCost = TransactionCost; result.initialDeposit = InitialDeposit; result.leverage = Leverage; result.maximum_open_positions = MaxOpenPositions; result.final_balance = InitialDeposit; result.balance_history = new List <double>(); result.balance_history.Add(InitialDeposit); #endregion for (int i = Window - 1; i < n_data; i++) { #region Regression double[,] xy = new double[Window, Basket.Length]; double[,] data = new double[Window, Basket.Length]; for (int j = 0; j < Window; j++) { for (int k = 0; k < Basket.Length; k++) { xy[j, k] = Price[k, i - j]; data[j, k] = Price[k, i - j]; } } double[] w = LinearRegression.Build(xy, Responsevariableindex); double[] x = new double[Basket.Length]; notes.Add(string.Join(",", w)); for (int j = 0; j < Basket.Length; j++) { TS[i - Window + 1] += w[j] * Price[j, i]; Weights[i - Window + 1, j] = w[j]; x[j] = Price[j, i]; } //add constant term TS[i - Window + 1] += w[Basket.Length]; Weights[i - Window + 1, Basket.Length] = w[Basket.Length]; #endregion #region Calculate bands double sum = 0; double sd = 0; double mean = 0; double upperBand, lowerBand, deviation; for (int j = 1; j < Window; j++) { sum += LinearRegression.Predict2(data, j, w); } mean = sum / Window; sum = 0; for (int j = 1; j < Window; j++) { double val = LinearRegression.Predict2(data, j, w); sum += ((val - mean) * (val - mean)); } sd = Math.Sqrt(sum / Window); deviation = Bandwidth * sd; upperBand = mean + deviation; lowerBand = mean - deviation; #endregion #region Locate current and previous positions int current_position = 0; int previous_position = 0; double current_val = LinearRegression.Predict2(data, 0, w); double previous_val = LinearRegression.Predict2(data, 1, w); if (current_val >= upperBand) { current_position = 1; } else if (current_val < upperBand && current_val > mean) { current_position = 2; } else if (current_val <= mean && current_val > lowerBand) { current_position = 3; } else { current_position = 4; } if (previous_val >= upperBand) { previous_position = 1; } else if (previous_val < upperBand && previous_val > mean) { previous_position = 2; } else if (previous_val <= mean && previous_val > lowerBand) { previous_position = 3; } else { previous_position = 4; } #endregion //######################### Close open trades ##################################################### foreach (TradeInfo trade in Trades) { double v = LinearRegression.Predict2(data, 0, trade.Coefficients); if (trade.Action == 1) { #region Check Buy Order if (v >= trade.TP) { //TP is hit. Winner :) trade.IsClosed = true; trade.close_index = i; result.tradedurations.Add(i - trade.open_index); double estimatepips = 0; double profit = GetProfit(trade, out estimatepips); updateResults(result, 1, profit, estimatepips); if (profit < 0) { result.total_TP_mismatch++; } } else if (v <= trade.SL) { //SL is hit. Loser :( trade.IsClosed = true; trade.close_index = i; result.tradedurations.Add(i - trade.open_index); double estimatepips = 0; double profit = GetProfit(trade, out estimatepips); updateResults(result, 1, profit, estimatepips); if (profit > 0) { result.total_SL_mismatch++; } } #endregion } else { #region Check Sell Order if (v <= trade.TP) { //TP is hit. Winner :) trade.IsClosed = true; trade.close_index = i; result.tradedurations.Add(i - trade.open_index); double estimatepips = 0; double profit = GetProfit(trade, out estimatepips); updateResults(result, 1, profit, estimatepips); if (profit < 0) { result.total_TP_mismatch++; } } else if (v >= trade.SL) { //SL is hit. Loser :( trade.IsClosed = true; trade.close_index = i; result.tradedurations.Add(i - trade.open_index); double estimatepips = 0; double profit = GetProfit(trade, out estimatepips); updateResults(result, 1, profit, estimatepips); if (profit > 0) { result.total_SL_mismatch++; } } #endregion } } Trades.RemoveAll(trade => trade.IsClosed); //################################## Open trade signals ###################################### if (Trades.Count < MaxOpenPositions) { if (previous_position == 1 && current_position == 2) { //Sell order #region Execute sell order double[] c = LinearRegression.NormalizeWeights(w, x, InversionDirection); int[] lotsizes = RiskManager.getTradeSizes(c, result.final_balance, Leverage); if (lotsizes != null) { TradeInfo trade = new TradeInfo(); trade.Action = -1; trade.Coefficients = w; trade.IsClosed = false; trade.TP = mean; trade.SL = mean + 2 * deviation; trade.TradeSizes = lotsizes; trade.open_index = i; trade.IsClosed = false; Trades.Add(trade); result.tradesizes.Add(LinearRegression.TotalNormalizedWeights(w, x, InversionDirection)); StandardizedWeights.Add(LinearRegression.StandardizeWeights(w, x, InversionDirection)); NormalizedWeights.Add(c); TradeSizes.Add(LinearRegression.getTradeSizes(c)); } else { result.total_reject_trades++; } #endregion } else if (previous_position == 4 & current_position == 3) { //Buy order #region Execute buy order double[] c = LinearRegression.NormalizeWeights(w, x, InversionDirection); int[] lotsizes = RiskManager.getTradeSizes(c, result.final_balance, Leverage); if (lotsizes != null) { TradeInfo trade = new TradeInfo(); trade.Action = -1; trade.Coefficients = w; trade.IsClosed = false; trade.TP = mean; trade.SL = mean - 2 * deviation; trade.TradeSizes = lotsizes; trade.open_index = i; trade.IsClosed = false; Trades.Add(trade); result.tradesizes.Add(LinearRegression.TotalNormalizedWeights(w, x, InversionDirection)); StandardizedWeights.Add(LinearRegression.StandardizeWeights(w, x, InversionDirection)); NormalizedWeights.Add(c); TradeSizes.Add(LinearRegression.getTradeSizes(c)); } else { result.total_reject_trades++; } #endregion } } //##################################################################################### } System.Windows.Forms.SaveFileDialog sf = new System.Windows.Forms.SaveFileDialog(); sf.Filter = "CSV file|*.csv"; sf.InitialDirectory = System.Windows.Forms.Application.StartupPath; if (sf.ShowDialog() != System.Windows.Forms.DialogResult.OK) { return(result); } using (System.IO.StreamWriter sw = new StreamWriter(sf.FileName)) { string header = string.Join(",", Basket); header = header + "," + header + "," + "Total," + header; sw.WriteLine(header); for (int i = 0; i < NormalizedWeights.Count; i++) { string[] items = new string[Basket.Length * 3 + 1]; for (int j = 0; j < Basket.Length; j++) { items[j] = StandardizedWeights[i][j].ToString(); } for (int j = 0; j < Basket.Length; j++) { items[Basket.Length + j] = NormalizedWeights[i][j].ToString(); } items[Basket.Length * 2] = result.tradesizes[i].ToString(); for (int j = 0; j < Basket.Length; j++) { if (TradeSizes[i] == null) { items[Basket.Length * 2 + 1 + j] = "NA"; } else { items[Basket.Length * 2 + 1 + j] = TradeSizes[i][j].ToString(); } } sw.WriteLine(string.Join(",", items)); } sw.Close(); } result.postMortem(); //frmPlot plot1 = new frmPlot(); //plot1.Show(); //plot1.draw(TS, "", "", "", -1, notes.ToArray()); //frmPlot plot2 = new frmPlot(); //plot2.Show(); //plot2.draw(Weights, WeightNames.ToArray()); return(result); }