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);
        }