Portfolio-Modeller

Price Data Components
Series array that contains close prices for each barSeries array that contains open time of each barSeries array that contains open prices of each barSeries array that contains the highest prices of each barSeries array that contains the lowest prices of each bar
Orders Execution
Checks for the total of open orders
Miscellaneous
It issuies visual alerts to the screenImplements a curve of type %1Uses files from the file systemIt writes information to fileIt writes information to fileIt writes information to fileIt writes information to fileIt reads information from a file
0 Views
0 Downloads
0 Favorites
Portfolio-Modeller
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
#property description "Portfolio Modeller"
#property description "Advanced synthetic optimization and analysis"
#property description "Transcendreamer"
#property strict
#include <Math\Alglib\alglib.mqh>
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
#define MAX_SYMBOLS 32
#define MAX_LINES 512
#define FONTNAME "Verdana"
#define FONTSIZE 9
#define SPACING 15
#define XMARGIN 5
#define YMARGIN 25
#define EQUAL '='
#define SPACE ' '
#define NARROW 1
#define BOLD 2
#define HISTOGRAM 2
#define COLOR_INTERVAL clrRed
#define COLOR_FILTER clrMagenta
#define COLOR_BID_ASK clrRed
#define COLOR_MODEL clrRed
#define CLICK_PIXELS 1
#define KEY_LEFT 188
#define KEY_RIGHT 190
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
#property indicator_separate_window
#property indicator_buffers MAX_LINES
#property indicator_plots MAX_LINES
#property indicator_level1 0
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
input  string           ______GENERAL______="______GENERAL______";
input  string           Portfolio_Name="";
input  string           Portfolio_Formula="";
enum   ENUM_MODE        {formula,decomposition,consolidation,import,terminal,
                         basic28,fours35,threes35,fours105,threes420,twos210,indices
                        };
input  ENUM_MODE        Generation_Type=fours35;
input  string           Import_File="";

input  string           ______SCALING______="______SCALING______";
input  bool             Downscaling_Total=true;
input  double           Multiplicator_Total=1;
input  double           Portfolio_Value=0;

input  string           ______MODEL______="______MODEL______";
enum   ENUM_METHOD      {fixed,spread,trend,oscillator,hybrid,root,exponent,
                         fitting,principal,antiprincipal,volatility
                        };
input  ENUM_METHOD      Model_Type=fixed;
input  double           Model_Growth=0;
input  double           Model_Amplitude=0;
input  double           Model_Cycles=0;
input  double           Model_Phase=0;
input  bool             Model_Absolute=false;
input  bool             Model_Backward=false;
input  double           Target_RMSE=0;

input  string           ______PERIOD______="______PERIOD______";
input  ENUM_TIMEFRAMES  Timeframe=PERIOD_D1;
input  bool             Use_Time=false;
input  datetime         Start_Time=D'2012.01.01 00:00';
input  datetime         Finish_Time=D'2035.01.01 00:00';
input  int              History_Shift=100;
input  int              Optimization_Length=200;
input  bool             Movable_Lines=false;
input  int              Jumping_Bars=1;

input  string           ______LIMITS______="______LIMITS______";
input  int              Limit_History=1000;
input  int              Limit_Forward=1000;
input  int              Limit_Model=100;
input  int              Request_Bars=2000;

input  string           ______TIMING______="______TIMING______";
input  int              Delay_Seconds=0;
input  int              Sync_Seconds=60;
input  int              Timer_Seconds=0;

input  string           ______FILTERS______="______FILTERS______";
enum   ENUM_FILTER      {disabled,high_low,RMSE_min,RMSE_max,manual};
input  ENUM_FILTER      Filter_Type=disabled;
input  int              Filter_Shift=-10;
enum   ENUM_SIGN        {null,positive,negative};
input  ENUM_SIGN        Inversion_Mode=null;
input  int              Highest_From=1;
input  int              Highest_To=1;
input  int              Lowest_From=1;
input  int              Lowest_To=1;
input  ENUM_SIGN        Position_Highest=positive;
input  ENUM_SIGN        Position_Lowest=positive;
input  int              RMSE_Selection=1;
input  int              Manual_Selection=0;

input  string           ______ANALYSIS______="______ANALYSIS______";
input  int              Main_Period=0;
input  int              Fast_Period=0;
input  int              Slow_Period=0;
enum   ENUM_CHANNELS    {empty,standard,envelopes,transcendent,confidence1,confidence2,corridor,deviation};
input  ENUM_CHANNELS    Channels_Type=empty;
input  double           Channel_Size=2;
enum   ENUM_SIGNALS     {normal,zscore,MACD,WPR};
input  ENUM_SIGNALS     Signal_Transformation=normal;
input  int              Signal_Period=0;

input  string           ______EXPORT______="______EXPORT______";
input  string           CSV_Export_File="";
input  string           CSV_Separator=";";

#ifdef __MQL4__
input  string           ______OHLC______="______OHLC______";
input  bool             OHLC_Offline_Chart=false;
input  ENUM_TIMEFRAMES  Data_Timeframe=PERIOD_M1;
input  int              Chart_Timeframe=2;
input  double           Price_Start=100000;
#endif

input  string           ______CHART______="______CHART______";
input  double           Chart_Grid_Size=0;
input  bool             Realistic_Total=false;
input  bool             Draw_Histogram=false;
input  bool             Draw_Markers=false;
input  bool             Hide_Model=false;
input  bool             Hide_Total=false;
input  bool             Hide_By_Filter=false;
input  bool             Hide_Stream=false;
input  bool             Hide_Zero_Lots=false;
input  bool             Hide_Text_Data=false;
input  int              Text_Indent=0;
input  ENUM_BASE_CORNER Text_Corner=CORNER_LEFT_UPPER;

input  string           ______COLORS______="______COLORS______";
input  color            Main_Color=clrMagenta;
input  color            Signal_Color=clrRed;
input  int              Colors_Offset=96;

input  string           ______OTHER______="______OTHER______";
enum   ENUM_BID_ASK     {none,single,longs,shorts};
input  ENUM_BID_ASK     Show_Bid_Ask=none;
input  double           Commission_Rate=0;
input  string           Chart_Currency="USD";
input  int              Lots_Digits=2;
input  string           FX_Prefix="";
input  string           FX_Postfix="";
input  bool             Print_Details=false;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool     error;
long     chart;
int      window;
ulong    file_position;
string   acc_currency;
datetime saved_time;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool mode_stream;
ENUM_BID_ASK mode_spread;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
#ifdef __MQL4__
bool     OHLC_mode;
int      OHLC_handle;
long     OHLC_chart;
#endif
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int      variables,points,components;
int      num_symbols,num_combos,dim_size,num_model,num_total,num_first;
int      num_main,num_slow,num_fast,num_upper,num_lower,num_zscore,num_macd;
int      index_start,index_finish,index_filter;
int      bar_start,bar_finish,bar_filter,bar_trading;
int      draw_begin,draw_end,model_begin,model_end;
datetime time_start,time_finish,time_filter;
double   scale_total,scale_model;
double   bar_range,total_shift;
double   sum_spread,sum_margin,sum_comms,sum_value;
double   rmse,range,rmse2range;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string   COMBINATIONS[MAX_LINES];
string   SYMBOLS[MAX_SYMBOLS];
double   LOTS[MAX_SYMBOLS];
double   MODEL[],ROOTS[];
double   VALUE[MAX_SYMBOLS],RMSE[MAX_LINES];
color    COLORS[MAX_LINES];
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
struct   MASSIVE
  {
   int               total,sign,position;
   int               pointer[MAX_SYMBOLS];
   double            lot[MAX_SYMBOLS];
  };
MASSIVE  PORTFOLIOS[MAX_LINES];
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
struct   STREAM
  {
   double            buffer[];
  };
STREAM   BUFFERS[MAX_LINES];
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
struct   CACHE
  {
   string            symbol;
   double            equity[],data[];
   double            opening,filter;
   double            value;
  };
CACHE    DATA[MAX_SYMBOLS];
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnInit()
  {
   mode_spread=Show_Bid_Ask;
   mode_stream=Hide_Stream;

   SetupCombinations();
   SetupBuffers();

#ifdef __MQL4__
   FindOHLC();
#endif

   if(Timer_Seconds>0)
      EventSetTimer(Timer_Seconds);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   CleanAll();
   if(Timer_Seconds>0)
      EventKillTimer();
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {

   ArraySetAsSeries(time,true);

   if(time[0]!=saved_time && TimeCurrent()>=time[0]+Delay_Seconds)
     {
      UpdateFullChart();
      saved_time=time[0];
     }
   else
     {
      UpdateLastBar();
     }

   return(rates_total);

  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnTimer()
  {
   UpdateFullChart();
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void UpdateFullChart()
  {

   error=false;
   Print(Portfolio_Name+": Starting portfolio calculation...");

   CleanAll();

   SetupCombinations();
   SetupSymbols();

#ifdef __MQL5__
   RequestData();
#endif
   SetupIntervals();
   CalculateEquity();

   for(int n=1; n<=num_combos; n++)
      CalculateOptimization(n);

   CalculateFilters();
   CalculateSummarization();
   CalculateScaling();

   for(int n=1; n<=num_combos; n++)
      DrawPortfolio(n,true);
   DrawPortfolio(num_total,true);

   DrawModel();
   DrawIndicators(true);

   UpdateFormula();
   UpdateStatistics();

   HideByFilter();
   DrawChartGrid();
   UpdateStatus();
   ChartRedraw(chart);

   ExportCSV();

#ifdef __MQL4__
   PrepareOHLC();
   GenerateOHLC(true);
   RefreshOHLC(true);
#endif

  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void UpdateLastBar()
  {
   for(int n=1; n<=num_combos; n++)
      DrawPortfolio(n,false);
   DrawPortfolio(num_total,false);
   DrawIndicators(false);
   UpdateStatus();
#ifdef __MQL4__
   GenerateOHLC(false);
   RefreshOHLC(false);
#endif
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void SetupBuffers()
  {

   IndicatorSetInteger(INDICATOR_DIGITS,2);
   IndicatorSetString(INDICATOR_SHORTNAME,"Portfolio Modeller");

   error=false;
   chart=ChartID();
   window=ChartWindowFind();
   acc_currency=AccountInfoString(ACCOUNT_CURRENCY);

#ifdef __MQL4__
   OHLC_chart=0;
   OHLC_mode=OHLC_Offline_Chart;
#endif

   if(Portfolio_Name=="")
     {
      Alert("Empty portfolio name!");
      error=true;
      return;
     }

   SetPlotName(num_first,Hide_Total?NULL:"Portfolio "+Portfolio_Name);
   SetPlotName(num_total,Hide_Total?NULL:"Total portfolio");
   SetPlotName(num_model,Hide_Model?NULL:"Model function");

   SetIndexBuffer(num_first,BUFFERS[num_first].buffer);
   SetIndexBuffer(num_total,BUFFERS[num_total].buffer);
   SetIndexBuffer(num_model,BUFFERS[num_model].buffer);

   SetPlotStyle(num_first,Hide_Total?DRAW_NONE:Draw_Histogram?DRAW_HISTOGRAM:DRAW_LINE,STYLE_SOLID,NARROW,Main_Color);
   SetPlotStyle(num_total,Hide_Total?DRAW_NONE:Draw_Markers?DRAW_ARROW:DRAW_LINE,STYLE_SOLID,mode_stream?NARROW:BOLD,Main_Color);
   SetPlotStyle(num_model,Hide_Model?DRAW_NONE:DRAW_LINE,STYLE_SOLID,NARROW,COLOR_MODEL);

   int offset=Colors_Offset%128;
   MathSrand(Colors_Offset);

   for(int n=1; n<=num_combos; n++)
     {
      int r=MathRand()%128+offset;
      int g=MathRand()%128+offset;
      int b=MathRand()%128+offset;
      COLORS[n]=color(r+g*256+b*65536);
      SetIndexBuffer(n,BUFFERS[n].buffer);
      SetPlotName(n,mode_stream?NULL:"Portfolio #"+string(n));
      SetPlotStyle(n,DRAW_LINE,STYLE_SOLID,NARROW,COLORS[n]);
     }

   SetPlotName(num_main,(Main_Period==0)?NULL:"Main Average");
   SetPlotName(num_fast,(Fast_Period==0)?NULL:"Fast Average");
   SetPlotName(num_slow,(Slow_Period==0)?NULL:"Slow Average");
   SetPlotName(num_upper,(Channels_Type==empty)?NULL:"Upper Boundary");
   SetPlotName(num_lower,(Channels_Type==empty)?NULL:"Lower Boundary");
   SetPlotName(num_zscore,NULL);
   SetPlotName(num_macd,NULL);

   SetIndexBuffer(num_main,BUFFERS[num_main].buffer,(Main_Period==0)?INDICATOR_CALCULATIONS:INDICATOR_DATA);
   SetIndexBuffer(num_fast,BUFFERS[num_fast].buffer,(Fast_Period==0)?INDICATOR_CALCULATIONS:INDICATOR_DATA);
   SetIndexBuffer(num_slow,BUFFERS[num_slow].buffer,(Slow_Period==0)?INDICATOR_CALCULATIONS:INDICATOR_DATA);
   SetIndexBuffer(num_upper,BUFFERS[num_upper].buffer,(Channels_Type==empty)?INDICATOR_CALCULATIONS:INDICATOR_DATA);
   SetIndexBuffer(num_lower,BUFFERS[num_lower].buffer,(Channels_Type==empty)?INDICATOR_CALCULATIONS:INDICATOR_DATA);
   SetIndexBuffer(num_zscore,BUFFERS[num_zscore].buffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(num_macd,BUFFERS[num_macd].buffer,INDICATOR_CALCULATIONS);

   SetPlotStyle(num_main,DRAW_LINE,STYLE_DOT,Draw_Histogram?HISTOGRAM:NARROW,Signal_Color);
   SetPlotStyle(num_fast,DRAW_LINE,STYLE_DOT,Draw_Histogram?HISTOGRAM:NARROW,Signal_Color);
   SetPlotStyle(num_slow,DRAW_LINE,STYLE_DOT,Draw_Histogram?HISTOGRAM:NARROW,Signal_Color);
   SetPlotStyle(num_upper,DRAW_LINE,STYLE_DOT,Draw_Histogram?HISTOGRAM:NARROW,Signal_Color);
   SetPlotStyle(num_lower,DRAW_LINE,STYLE_DOT,Draw_Histogram?HISTOGRAM:NARROW,Signal_Color);
   SetPlotStyle(num_zscore,DRAW_NONE,STYLE_DOT,Draw_Histogram?HISTOGRAM:NARROW,Signal_Color);
   SetPlotStyle(num_macd,DRAW_NONE,STYLE_DOT,Draw_Histogram?HISTOGRAM:NARROW,Signal_Color);

   if(Signal_Transformation!=normal)
     {
      SetPlotStyle(num_total,DRAW_NONE,STYLE_DOT,NARROW,Signal_Color);
      for(int n=1; n<=num_combos; n++)
         SetPlotName(n,NULL);
     }

   for(int n=dim_size; n<MAX_LINES; n++)
      SetPlotName(n,NULL);

   for(int i=0; i<MAX_LINES; i++)
      ArraySetAsSeries(BUFFERS[i].buffer,true);

  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void SetPlotStyle(int i,int type,int style,int width,color colour)
  {
#ifdef __MQL4__
   SetIndexStyle(i,type,style,width,colour);
#else
   PlotIndexSetInteger(i,PLOT_DRAW_TYPE,type);
   PlotIndexSetInteger(i,PLOT_LINE_STYLE,style);
   PlotIndexSetInteger(i,PLOT_LINE_WIDTH,width);
   PlotIndexSetInteger(i,PLOT_LINE_COLOR,colour);
#endif
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void SetPlotName(int i,string name)
  {
#ifdef __MQL4__
   SetIndexLabel(i,name);
#else
   PlotIndexSetString(i,PLOT_LABEL,name);
#endif
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CleanAll()
  {

   ZeroMemory(PORTFOLIOS);
   ZeroMemory(DATA);
   ZeroMemory(SYMBOLS);
   ZeroMemory(LOTS);

   for(int n=ObjectsTotal(chart,window,-1); n>=1; n--)
     {
      string name=ObjectName(chart,n-1,window);
      if(StringFind(name,"Formula-label-"+Portfolio_Name+"-")!=-1)
         ObjectDelete(chart,name);
      if(StringFind(name,"Data-label-"+Portfolio_Name+"-")!=-1)
         ObjectDelete(chart,name);
      if(StringFind(name,"Grid-level-"+Portfolio_Name+":")!=-1)
         ObjectDelete(chart,name);
      if(StringFind(name,"Z-level-upper-"+Portfolio_Name)!=-1)
         ObjectDelete(chart,name);
      if(StringFind(name,"Z-level-lower-"+Portfolio_Name)!=-1)
         ObjectDelete(chart,name);
      if(StringFind(name,"Portfolio-bid-"+Portfolio_Name)!=-1)
         ObjectDelete(chart,name);
      if(StringFind(name,"Portfolio-ask-"+Portfolio_Name)!=-1)
         ObjectDelete(chart,name);
      if(StringFind(name,"Portfolio-last-"+Portfolio_Name)!=-1)
         ObjectDelete(chart,name);
      if(StringFind(name,"CHART_"+Portfolio_Name)!=-1)
         ObjectDelete(chart,name);
     }

   if(!Movable_Lines)
     {
      ObjectDelete(chart,"Line-start-bar-"+Portfolio_Name);
      ObjectDelete(chart,"Line-finish-bar-"+Portfolio_Name);
      ObjectDelete(chart,"Line-filter-bar-"+Portfolio_Name);
     }

   GlobalVariableDel("Portfolio-"+Portfolio_Name);
   GlobalVariableDel("Quality-"+Portfolio_Name);
   GlobalVariableDel("Model-"+Portfolio_Name);
   GlobalVariableDel("Upper-"+Portfolio_Name);
   GlobalVariableDel("Lower-"+Portfolio_Name);
   GlobalVariableDel("Main-"+Portfolio_Name);
   GlobalVariableDel("Fast-"+Portfolio_Name);
   GlobalVariableDel("Slow-"+Portfolio_Name);

  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {

//---

   if(id==CHARTEVENT_KEYDOWN)
      while(Movable_Lines)
        {
         int shift_bars=0;
         if(int(lparam)==KEY_LEFT)
            shift_bars=+Jumping_Bars;
         if(int(lparam)==KEY_RIGHT)
            shift_bars=-Jumping_Bars;
         if(shift_bars==0)
            break;

         bar_start   =shift_bars+iBarShift(_Symbol,_Period,time_start);
         bar_finish  =shift_bars+iBarShift(_Symbol,_Period,time_finish);
         bar_filter  =shift_bars+iBarShift(_Symbol,_Period,time_filter);

         time_start  =iTime(_Symbol,_Period,bar_start);
         time_finish =iTime(_Symbol,_Period,bar_finish);
         time_filter =iTime(_Symbol,_Period,bar_filter);

         ObjectSetInteger(chart,"Line-start-bar-"+Portfolio_Name,OBJPROP_TIME,0,time_start);
         ObjectSetInteger(chart,"Line-finish-bar-"+Portfolio_Name,OBJPROP_TIME,0,time_finish);
         ObjectSetInteger(chart,"Line-filter-bar-"+Portfolio_Name,OBJPROP_TIME,0,time_filter);

         UpdateFullChart();
         break;
        }

//---

   if(id==CHARTEVENT_OBJECT_DRAG)
      if(StringFind(sparam,"-bar-"+Portfolio_Name)!=-1)
        {
         if((TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT)&0x80)!=0)
            while(Movable_Lines)
              {
               datetime oldTime=0;
               if(sparam=="Line-start-bar-"+Portfolio_Name)
                  oldTime=time_start;
               else
                  if(sparam=="Line-finish-bar-"+Portfolio_Name)
                     oldTime=time_finish;
                  else
                     if(sparam=="Line-filter-bar-"+Portfolio_Name)
                        oldTime=time_filter;
                     else
                        break;

               datetime newTime=(datetime)ObjectGetInteger(chart,sparam,OBJPROP_TIME,0);
               int oldBar=iBarShift(_Symbol,_Period,oldTime);
               int newBar=iBarShift(_Symbol,_Period,newTime);
               int shiftBars=newBar-oldBar;

               if(shiftBars==0)
                  break;

               bar_start   =iBarShift(_Symbol,_Period,time_start)+shiftBars;
               bar_finish  =iBarShift(_Symbol,_Period,time_finish)+shiftBars;
               bar_filter  =iBarShift(_Symbol,_Period,time_filter)+shiftBars;

               time_start  =iTime(_Symbol,_Period,bar_start);
               time_finish =iTime(_Symbol,_Period,bar_finish);
               time_filter =iTime(_Symbol,_Period,bar_filter);

               ObjectSetInteger(chart,"Line-start-bar-"+Portfolio_Name,OBJPROP_TIME,0,time_start);
               ObjectSetInteger(chart,"Line-finish-bar-"+Portfolio_Name,OBJPROP_TIME,0,time_finish);
               ObjectSetInteger(chart,"Line-filter-bar-"+Portfolio_Name,OBJPROP_TIME,0,time_filter);

               break;
              }
         UpdateFullChart();
        }

//---

   if(id==CHARTEVENT_OBJECT_CLICK)
      if(StringFind(sparam,"Data-label-"+Portfolio_Name)!=-1)
        {
         if(mode_spread==none)
           {
            mode_spread=longs;
            UpdateStatus();
           }
         else
            if(mode_spread==longs)
              {
               mode_spread=shorts;
               UpdateStatus();
              }
            else
               if(mode_spread==shorts)
                 {
                  mode_spread=single;
                  UpdateStatus();
                 }
               else
                  if(mode_spread==single)
                    {
                     mode_spread=none;
                     UpdateStatus();
                    }
        }

//---

   if(id==CHARTEVENT_OBJECT_CLICK)
      if(StringFind(sparam,"Formula-label-"+Portfolio_Name)!=-1)
        {
         mode_stream=!mode_stream;
         num_model=mode_stream?num_combos+1:0;
         num_total=mode_stream?0:num_combos+1;
         UpdateFullChart();
        }

//---

   if(id==CHARTEVENT_CLICK)
      if((TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL)&0x80)!=0)
        {
         double price1,price2;
         datetime time;
         int subwindow=0;

         ChartXYToTimePrice(chart,(int)lparam,(int)dparam-CLICK_PIXELS,subwindow,time,price1);
         ChartXYToTimePrice(chart,(int)lparam,(int)dparam+CLICK_PIXELS,subwindow,time,price2);

         if(subwindow==window)
           {
            int bar=iBarShift(NULL,0,time);
            bool empty_select=true;
            for(int n=1; n<=num_combos; n++)
               if(BUFFERS[n].buffer[bar]>=price2 && BUFFERS[n].buffer[bar]<price1)
                 {
                  SetPlotStyle(n,DRAW_LINE,STYLE_SOLID,NARROW,COLORS[n]);
                  empty_select=false;
                 }
               else
                  SetPlotStyle(n,DRAW_LINE,STYLE_SOLID,NARROW,clrNONE);
            if(empty_select)
               for(int n=1; n<=num_combos; n++)
                  SetPlotStyle(n,DRAW_LINE,STYLE_SOLID,NARROW,COLORS[n]);
           }
        }

//---

  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void RequestData()
  {
   double data1[];
   double data2[];
   for(int k=0; k<components; k++)
      while(true)
        {
         int n=CopyClose(DATA[k].symbol,Timeframe,0,Request_Bars,data1);
         int m=CopyClose(DATA[k].symbol,_Period,0,Request_Bars,data2);
         if(m==Request_Bars)
            if(n==Request_Bars)
               break;
         //string name="CHART_"+Portfolio_Name+"_"+DATA[k].symbol;
         //ObjectCreate(chart,name,OBJ_CHART,window,0,0);
         //ObjectSetInteger(chart,name,OBJPROP_XOFFSET,1);
         //ObjectSetInteger(chart,name,OBJPROP_YOFFSET,1);
         //ObjectSetInteger(chart,name,OBJPROP_XSIZE,1);
         //ObjectSetInteger(chart,name,OBJPROP_YSIZE,1);
         //ObjectSetInteger(chart,name,OBJPROP_PERIOD,_Period);
         //ObjectSetString(chart,name,OBJPROP_SYMBOL,DATA[k].symbol);
        }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void SetupIntervals()
  {

   if(error)
      return;

   bool reset_lines=false;
   bool use_filter=(Filter_Type==high_low);

//---

   if(Movable_Lines)
     {

      time_start      =(datetime)ObjectGetInteger(chart,"Line-start-bar-"+Portfolio_Name,OBJPROP_TIME,0);
      time_finish     =(datetime)ObjectGetInteger(chart,"Line-finish-bar-"+Portfolio_Name,OBJPROP_TIME,0);
      time_filter     =(datetime)ObjectGetInteger(chart,"Line-filter-bar-"+Portfolio_Name,OBJPROP_TIME,0);

      if(!use_filter)
         time_filter=time_finish;

      index_start    =iBarShift(_Symbol,Timeframe,time_start);
      index_finish   =iBarShift(_Symbol,Timeframe,time_finish);
      index_filter   =iBarShift(_Symbol,Timeframe,time_filter);

      if(time_start==0 || time_finish==0 || time_filter==0)
         reset_lines=true;
     }

//---

   if(!Movable_Lines || reset_lines)
     {
      index_start    =Use_Time?iBarShift(_Symbol,Timeframe,Start_Time):History_Shift+Optimization_Length;
      index_finish   =Use_Time?iBarShift(_Symbol,Timeframe,Finish_Time):History_Shift;
      index_filter   =index_finish+Filter_Shift;

      if(!use_filter)
         index_filter=index_finish;

      if(index_start<0)
         index_start=0;

      if(index_finish<0)
         index_finish=0;

      if(index_filter<0)
         index_filter=0;

      time_start  =iTime(_Symbol,Timeframe,index_start);
      time_finish =iTime(_Symbol,Timeframe,index_finish);
      time_filter =iTime(_Symbol,Timeframe,index_filter);
     }

//---

   datetime time_current=time_start;
   int base_time=PeriodSeconds(Timeframe);
   while(time_current<=time_finish && time_current>=time_start)
     {
      bool check=true;
      for(int k=0; k<components; k++)
         if(iBarShift(DATA[k].symbol,Timeframe,time_current,true)==-1)
            check=false;
      if(check)
        {
         time_start=time_current;
         break;
        }
      time_current+=base_time;
     }

//---

   time_current=time_finish;
   while(time_current<=time_finish && time_current>=time_start)
     {
      bool check=true;
      for(int k=0; k<components; k++)
         if(iBarShift(DATA[k].symbol,Timeframe,time_current,true)==-1)
            check=false;
      if(check)
        {
         time_finish=time_current;
         break;
        }
      time_current-=base_time;
     }

//---

   index_finish=iBarShift(_Symbol,Timeframe,time_finish);
   index_start =iBarShift(_Symbol,Timeframe,time_start);

   if(index_start<=index_finish || time_start>=time_finish)
     {
      Alert("Incorrect interval settings!");
      error=true;
      return;
     }

//---

   PlaceVertical("Line-start-bar-"+Portfolio_Name,time_start,COLOR_INTERVAL,STYLE_DASH,true,Movable_Lines,Movable_Lines);
   PlaceVertical("Line-finish-bar-"+Portfolio_Name,time_finish,COLOR_INTERVAL,STYLE_DASH,true,Movable_Lines,Movable_Lines);
   PlaceVertical("Line-filter-bar-"+Portfolio_Name,time_filter,COLOR_FILTER,STYLE_DOT,true,Movable_Lines,Movable_Lines);

   long periods=use_filter?OBJ_ALL_PERIODS:OBJ_NO_PERIODS;
   ObjectSetInteger(chart,"Line-filter-bar-"+Portfolio_Name,OBJPROP_TIMEFRAMES,periods);

   ObjectSetString(chart,"Line-start-bar-"+Portfolio_Name,OBJPROP_TEXT,TimeToString(time_start));
   ObjectSetString(chart,"Line-finish-bar-"+Portfolio_Name,OBJPROP_TEXT,TimeToString(time_finish));
   ObjectSetString(chart,"Line-filter-bar-"+Portfolio_Name,OBJPROP_TEXT,TimeToString(time_filter));

//---

   int bars       =Bars(_Symbol,_Period);
   bar_start      =iBarShift(_Symbol,_Period,time_start);
   bar_finish     =iBarShift(_Symbol,_Period,time_finish);
   bar_filter     =iBarShift(_Symbol,_Period,time_filter);
   bar_trading    =MathMin(bar_finish,bar_filter);
   draw_begin     =MathMin(bar_start+Limit_History,bars-1);
   draw_end       =MathMax(bar_finish-Limit_Forward,0);
   model_begin    =MathMin(bar_start+Limit_Model,bars-1);
   model_end      =MathMax(bar_finish-Limit_Model,0);

//---

   if(bar_start==-1 || bar_finish==-1 || bar_filter==-1)
     {
      Alert(time_start,"   :   ",time_finish);
      Alert(time_start,"   :   ",time_finish);
      Alert("Data buffers not ready!");
      error=true;
      return;
     }

//---

   if(iTime(_Symbol,_Period,bars-1)<=time_start)
      bar_range=bar_start-bar_finish;
   else
      bar_range=PeriodSeconds(Timeframe)/PeriodSeconds(_Period)*(index_start-index_finish);

  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void SetupSymbols()
  {
   if(error)
      return;

   components=0;

   for(int n=1; n<=num_combos; n++)
     {
      ArrayInitialize(PORTFOLIOS[n].pointer,-1);
      SetupFormula(COMBINATIONS[n]);

      for(int i=0; i<num_symbols; i++)
         for(int k=0; k<MAX_SYMBOLS; k++)
           {

            if(SYMBOLS[i]==NULL)
               break;
            if(SYMBOLS[i]=="")
               break;

            if(SYMBOLS[i]==DATA[k].symbol)
              {
               PORTFOLIOS[n].pointer[i]=k;
               PORTFOLIOS[n].lot[i]+=LOTS[i];
               PORTFOLIOS[n].total++;
               break;
              }

            if(DATA[k].symbol==NULL)
              {
               DATA[k].symbol=SYMBOLS[i];
               PORTFOLIOS[n].pointer[i]=k;
               PORTFOLIOS[n].lot[i]=LOTS[i];
               PORTFOLIOS[n].total++;
               components++;
               break;
              }

           }

      if(PORTFOLIOS[n].total==0)
        {
         Alert("Incorrect portfolio combination: ",COMBINATIONS[n]);
         error=true;
         return;
        }
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void SetupFormula(string formula)
  {

   variables=0;

   string lines[],parts[];
#ifdef __MQL4__
   formula=StringTrimLeft(formula);
   formula=StringTrimRight(formula);
#else
   StringTrimLeft(formula);
   StringTrimRight(formula);
#endif
   variables=StringSplit(formula,SPACE,lines);

   for(int i=0; i<variables; i++)
     {

      if(lines[i]=="")
        {
         Alert("Incorrect portfolio formula: \""+formula+"\"");
         error=true;
         return;
        }

      int n=StringSplit(lines[i],EQUAL,parts);

      if(n==2)
        {
         SYMBOLS[i]=parts[0];
         LOTS[i]=StringToDouble(parts[1]);
        }
      else
         if(n==1)
           {
            SYMBOLS[i]=parts[0];
            LOTS[i]=1;
           }
         else
           {
            Alert("Incorrect portfolio formula: \""+formula+"\"");
            error=true;
            return;
           }

      if(Generation_Type!=consolidation && Generation_Type!=terminal)
         SYMBOLS[i]=FX_Prefix+SYMBOLS[i]+FX_Postfix;

      if(SymbolInfoDouble(SYMBOLS[i],SYMBOL_POINT)==0)
        {
         Alert("Missing symbol in Market Watch: ",SYMBOLS[i]);
         error=true;
         return;
        }

     }

  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CalculateEquity()
  {

   if(error)
      return;

   points=0;
   int base_time=PeriodSeconds(Timeframe);
   int max_points=int((time_finish-time_start)/base_time)+1;
   datetime current_time=Model_Backward?time_finish:time_start;
   if(Model_Backward)
      base_time*=-1;

   for(int k=0; k<components; k++)
      ArrayResize(DATA[k].equity,max_points);

   while(current_time<=time_finish && current_time>=time_start)
     {
      points++;
      for(int k=0; k<components; k++)
        {
         int shift=iBarShift(DATA[k].symbol,Timeframe,current_time,true);
         if(shift==-1)
           {
            points--;
            break;
           }
         double closing=iClose(DATA[k].symbol,Timeframe,shift);
         double value=ContractValue(DATA[k].symbol,current_time,Timeframe,Chart_Currency);
         if(points==1)
            DATA[k].opening=closing;
         DATA[k].equity[points-1]=(closing-DATA[k].opening)*value;
        }
      current_time+=base_time;
     }

   for(int k=0; k<components; k++)
     {
      int shift=iBarShift(DATA[k].symbol,Timeframe,time_filter);
      double close=iClose(DATA[k].symbol,Timeframe,shift);
      DATA[k].value=ContractValue(DATA[k].symbol,time_filter,Timeframe,Chart_Currency);
      DATA[k].filter=(close-DATA[k].opening)*DATA[k].value;
     }

   for(int k=0; k<components; k++)
     {
      ArraySetAsSeries(DATA[k].data,true);
      ArrayResize(DATA[k].data,draw_begin+1);
     }

   for(int j=draw_begin; j>=draw_end; j--)
      for(int k=0; k<components; k++)
        {
         datetime time=iTime(_Symbol,_Period,j);
         int shift=iBarShift(DATA[k].symbol,_Period,time);
         double value=ContractValue(DATA[k].symbol,time,PERIOD_CURRENT,Chart_Currency);
         double closing=iClose(DATA[k].symbol,_Period,shift);
         DATA[k].data[j]=(closing-DATA[k].opening)*value;
        }

   if(points<5)
     {
      Alert("Insufficient history data!");
      error=true;
      return;
     }

  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CalculateOptimization(int number)
  {

   if(error)
      return;

   variables=PORTFOLIOS[number].total;
   ArrayResize(MODEL,points);
   ArrayResize(ROOTS,variables);

//---

   if(Model_Type==fixed)
     {
      for(int i=0; i<variables; i++)
         ROOTS[i]=PORTFOLIOS[number].lot[i];
     }

//---

   if(Model_Type==spread)
     {
      int info,i,j;
      int roots=variables-1;
      CLinearModelShell LM;
      CLRReportShell AR;
      CLSFitReportShell report;
      CMatrixDouble MATRIX(points,variables);

      for(i=0; i<variables; i++)
         for(j=0; j<points; j++)
            MATRIX[j].Set(i,DATA[PORTFOLIOS[number].pointer[i]].equity[j]);

      CAlglib::LRBuildZ(MATRIX,points,variables-1,info,LM,AR);

      if(info<0)
        {
         Alert("Error in regression model!");
         error=true;
         return;
        }

      CAlglib::LRUnpack(LM,ROOTS,roots);
      ArrayResize(ROOTS,variables);
      ROOTS[variables-1]=-1;
     }

//---

   if(Model_Type==trend)
     {
      int info,i,j;
      CLinearModelShell LM;
      CLRReportShell AR;
      CMatrixDouble MATRIX(points,variables+1);

      if(Model_Growth==0)
        {
         Alert("Zero model growth!");
         error=true;
         return;
        }

      for(j=0; j<points; j++)
        {
         double x=(double)j/(points-1)-Model_Phase;
         if(Model_Absolute)
            x=MathAbs(x);
         MODEL[j]=Model_Growth*x;
        }

      double shift=-MODEL[0];
      if(shift!=0)
         for(j=0; j<points; j++)
            MODEL[j]+=shift;

      for(i=0; i<variables; i++)
         for(j=0; j<points; j++)
            MATRIX[j].Set(i,DATA[PORTFOLIOS[number].pointer[i]].equity[j]);

      for(j=0; j<points; j++)
         MATRIX[j].Set(variables,MODEL[j]);

      CAlglib::LRBuildZ(MATRIX,points,variables,info,LM,AR);

      if(info<0)
        {
         Alert("Error in regression model!");
         error=true;
         return;
        }

      CAlglib::LRUnpack(LM,ROOTS,variables);
     }

//---

   if(Model_Type==root)
     {
      int info,i,j;
      CLinearModelShell LM;
      CLRReportShell AR;
      CMatrixDouble MATRIX(points,variables+1);

      if(Model_Growth==0)
        {
         Alert("Zero model growth!");
         error=true;
         return;
        }

      for(j=0; j<points; j++)
        {
         double x=(double)j/(points-1)-Model_Phase;
         int sign=(int)MathSign(x);
         if(Model_Absolute)
            sign=1;
         MODEL[j]=sign*Model_Growth*MathSqrt(MathAbs(x));
        }

      double shift=-MODEL[0];
      if(shift!=0)
         for(j=0; j<points; j++)
            MODEL[j]+=shift;

      for(i=0; i<variables; i++)
         for(j=0; j<points; j++)
            MATRIX[j].Set(i,DATA[PORTFOLIOS[number].pointer[i]].equity[j]);

      for(j=0; j<points; j++)
         MATRIX[j].Set(variables,MODEL[j]);

      CAlglib::LRBuildZ(MATRIX,points,variables,info,LM,AR);

      if(info<0)
        {
         Alert("Error in regression model!");
         error=true;
         return;
        }

      CAlglib::LRUnpack(LM,ROOTS,variables);
     }

//---

   if(Model_Type==exponent)
     {
      int info,i,j;
      CLinearModelShell LM;
      CLRReportShell AR;
      CMatrixDouble MATRIX(points,variables+1);

      if(Model_Growth==0)
        {
         Alert("Zero model growth!");
         error=true;
         return;
        }

      for(j=0; j<points; j++)
        {
         double x=(double)j/(points-1)*Model_Cycles-Model_Phase;
         if(Model_Absolute)
            x=MathAbs(x);
         MODEL[j]=Model_Growth*MathExp(x);
        }

      double shift=-MODEL[0];
      if(shift!=0)
         for(j=0; j<points; j++)
            MODEL[j]+=shift;

      for(i=0; i<variables; i++)
         for(j=0; j<points; j++)
            MATRIX[j].Set(i,DATA[PORTFOLIOS[number].pointer[i]].equity[j]);

      for(j=0; j<points; j++)
         MATRIX[j].Set(variables,MODEL[j]);

      CAlglib::LRBuildZ(MATRIX,points,variables,info,LM,AR);

      if(info<0)
        {
         Alert("Error in regression model!");
         error=true;
         return;
        }

      CAlglib::LRUnpack(LM,ROOTS,variables);
     }

//---

   if(Model_Type==oscillator)
     {
      int info,i,j;
      CLinearModelShell LM;
      CLRReportShell AR;
      CMatrixDouble MATRIX(points,variables+1);

      if(Model_Cycles==0)
        {
         Alert("Zero model cycles!");
         error=true;
         return;
        }

      if(Model_Amplitude==0)
        {
         Alert("Zero model amplitude!");
         error=true;
         return;
        }

      for(j=0; j<points; j++)
        {
         double x=(double)j/(points-1)*Model_Cycles-Model_Phase;
         if(Model_Absolute)
            x=MathAbs(x);
         MODEL[j]=Model_Amplitude*MathSin(2*M_PI*x);
        }

      double shift=-MODEL[0];
      if(shift!=0)
         for(j=0; j<points; j++)
            MODEL[j]+=shift;

      for(i=0; i<variables; i++)
         for(j=0; j<points; j++)
            MATRIX[j].Set(i,DATA[PORTFOLIOS[number].pointer[i]].equity[j]);

      for(j=0; j<points; j++)
         MATRIX[j].Set(variables,MODEL[j]);

      CAlglib::LRBuildZ(MATRIX,points,variables,info,LM,AR);

      if(info<0)
        {
         Alert("Error in regression model!");
         error=true;
         return;
        }

      CAlglib::LRUnpack(LM,ROOTS,variables);
     }

//---

   if(Model_Type==hybrid)
     {
      int info,i,j;
      CLinearModelShell LM;
      CLRReportShell AR;
      CMatrixDouble MATRIX(points,variables+1);

      if(Model_Growth==0)
        {
         Alert("Zero model growth!");
         error=true;
         return;
        }

      if(Model_Cycles==0)
        {
         Alert("Zero model cycles!");
         error=true;
         return;
        }

      if(Model_Amplitude==0)
        {
         Alert("Zero model amplitude!");
         error=true;
         return;
        }

      for(j=0; j<points; j++)
        {
         double x=(double)j/(points-1)*Model_Cycles-Model_Phase;
         if(Model_Absolute)
            x=MathAbs(x);
         MODEL[j]=Model_Amplitude*MathSin(2*M_PI*x)+Model_Growth*x;
        }

      double shift=-MODEL[0];
      if(shift!=0)
         for(j=0; j<points; j++)
            MODEL[j]+=shift;

      for(i=0; i<variables; i++)
         for(j=0; j<points; j++)
            MATRIX[j].Set(i,DATA[PORTFOLIOS[number].pointer[i]].equity[j]);

      for(j=0; j<points; j++)
         MATRIX[j].Set(variables,MODEL[j]);

      CAlglib::LRBuildZ(MATRIX,points,variables,info,LM,AR);

      if(info<0)
        {
         Alert("Error in regression model!");
         error=true;
         return;
        }

      CAlglib::LRUnpack(LM,ROOTS,variables);
     }

//---

   if(Model_Type==fitting)
     {
      int info,i,j;
      CLSFitReportShell report;
      CMatrixDouble MATRIX(points,variables);
      CMatrixDouble CONSTRAIN(1,variables+1);

      CONSTRAIN[0].Set(variables,1);

      for(i=0; i<variables; i++)
         CONSTRAIN[0].Set(i,1);

      for(i=0; i<variables; i++)
         for(j=0; j<points; j++)
            MATRIX[j].Set(i,DATA[PORTFOLIOS[number].pointer[i]].equity[j]);

      for(j=0; j<points; j++)
         MODEL[j]=0;

      CAlglib::LSFitLinearC(MODEL,MATRIX,CONSTRAIN,points,variables,1,info,ROOTS,report);

      if(info<0)
        {
         Alert("Error in linear fitting model!");
         error=true;
         return;
        }
     }

//---

   if(Model_Type==principal)
     {
      int info,i,j;
      double VAR[];
      ArrayResize(VAR,variables);
      CMatrixDouble MATRIX(points,variables);
      CMatrixDouble VECTOR(variables,variables);

      for(i=0; i<variables; i++)
         for(j=0; j<points; j++)
            MATRIX[j].Set(i,DATA[PORTFOLIOS[number].pointer[i]].equity[j]);

      CAlglib::PCABuildBasis(MATRIX,points,variables,info,VAR,VECTOR);

      if(info<0)
        {
         Alert("Error in principal component model!");
         error=true;
         return;
        }

      for(i=0; i<variables; i++)
         ROOTS[i]=VECTOR[i][variables-1];
     }

//---

   if(Model_Type==antiprincipal)
     {
      int info,i,j;
      double VAR[];
      ArrayResize(VAR,variables);
      CMatrixDouble MATRIX(points,variables);
      CMatrixDouble VECTOR(variables,variables);

      for(i=0; i<variables; i++)
         for(j=0; j<points; j++)
            MATRIX[j].Set(i,DATA[PORTFOLIOS[number].pointer[i]].equity[j]);

      CAlglib::PCABuildBasis(MATRIX,points,variables,info,VAR,VECTOR);

      if(info<0)
        {
         Alert("Error in principal component model!");
         error=true;
         return;
        }

      for(i=0; i<variables; i++)
         ROOTS[i]=VECTOR[i][0];
     }

//---

   if(Model_Type==volatility)
     {
      if(Model_Amplitude==0)
        {
         Alert("Zero model amplitude!");
         error=true;
         return;
        }

      for(int i=0; i<variables; i++)
        {
         double mean=0;
         double stdev=0;

         for(int j=0; j<points; j++)
            mean+=DATA[PORTFOLIOS[number].pointer[i]].equity[j];
         mean/=points;

         for(int j=0; j<points; j++)
            stdev+=MathPow(mean-DATA[PORTFOLIOS[number].pointer[i]].equity[j],2);
         stdev=MathSqrt(stdev/points);

         ROOTS[i]=Model_Amplitude/stdev;
         if(PORTFOLIOS[number].lot[i]<0)
            ROOTS[i]*=-1;
        }
     }

//---

   if(Filter_Type==RMSE_max || Filter_Type==RMSE_min || Target_RMSE>0)
     {
      double sumsq=0,count=0;
      for(int j=0; j<points; j++)
        {
         double equity=0;
         for(int i=0; i<variables; i++)
            equity+=DATA[PORTFOLIOS[number].pointer[i]].equity[j]*ROOTS[i];
         sumsq+=MathPow(equity-MODEL[j],2);
         count++;
        }
      RMSE[number]=MathSqrt(sumsq/count);
     }

//---

   if(Target_RMSE>0)
     {
      for(int i=0; i<variables; i++)
         ROOTS[i]=ROOTS[i]*Target_RMSE/RMSE[number];
      RMSE[number]=Target_RMSE;
     }

//---

   for(int i=0; i<variables; i++)
      PORTFOLIOS[number].lot[i]=ROOTS[i];

  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CalculateFilters()
  {

   if(error)
      return;

//---

   if(Print_Details)
      for(int n=1; n<=num_combos; n++)
        {
         string formula="";
         variables=PORTFOLIOS[n].total;
         for(int i=0; i<variables; i++)
           {
            string symbol=DATA[PORTFOLIOS[n].pointer[i]].symbol;
            string lots=DoubleToString(PORTFOLIOS[n].lot[i],Lots_Digits);
            formula+=(symbol+CharToString(EQUAL)+lots+CharToString(SPACE));
           }
         Print(Portfolio_Name+": Portfolio #",n,": ",formula);
        }

//---

   if(Filter_Type==disabled)
     {
      for(int n=1; n<=num_combos; n++)
         PORTFOLIOS[n].position=+1;
      for(int n=1; n<=num_combos; n++)
         PORTFOLIOS[n].sign=+1;
      if(Print_Details)
         Print(Portfolio_Name+": All portfolios included as positive");
      return;
     }

//---

   if(Filter_Type==manual)
     {
      if(Manual_Selection>num_combos || Manual_Selection<1)
        {
         Alert("Incorrect manual selection!");
         error=true;
         return;
        }

      for(int n=1; n<=num_combos; n++)
        {
         PORTFOLIOS[n].position=0;
         PORTFOLIOS[n].sign=0;
        }

      PORTFOLIOS[Manual_Selection].position=+1;
      PORTFOLIOS[Manual_Selection].sign=+1;

      if(Print_Details)
         Print("Portfolio #",Manual_Selection," included as positive");

      return;
     }

//---

   if(Filter_Type==RMSE_max || Filter_Type==RMSE_min)
     {
      if(RMSE_Selection>num_combos || RMSE_Selection<1)
        {
         Alert("Incorrect RMSE selection!");
         error=true;
         return;
        }

      double rmse_data[][2];
      ArrayResize(rmse_data,num_combos);
      ArrayInitialize(rmse_data,0);

      for(int n=1; n<=num_combos; n++)
        {
         if(Filter_Type==RMSE_min)
            rmse_data[n-1][0]=+RMSE[n];
         else
            rmse_data[n-1][0]=-RMSE[n];
         rmse_data[n-1][1]=n;
        }

      ArraySort(rmse_data);

      for(int n=1; n<=num_combos; n++)
        {
         PORTFOLIOS[n].position=0;
         PORTFOLIOS[n].sign=1;
        }

      for(int m=1; m<=RMSE_Selection; m++)
        {
         int n=(int)rmse_data[m-1][1];
         PORTFOLIOS[n].position=+1;
         PORTFOLIOS[n].sign=+1;
         if(Print_Details)
            Print(Portfolio_Name+": Portfolio #",n," included positive by RMSE");
        }

      return;
     }

//---

   if(Filter_Type==high_low)
     {
      if(Highest_From>num_combos || Highest_From<1 || Highest_To>num_combos || Highest_To<1 ||
         Lowest_From>num_combos  || Lowest_From<1  || Lowest_To>num_combos  || Lowest_To<1)
        {
         Alert("Incorrect filter selection!");
         error=true;
         return;
        }

      int filter[];
      int invert[];
      double equity[][2];

      ArrayResize(equity,num_combos);
      ArrayResize(filter,num_combos);
      ArrayResize(invert,num_combos);

      ArrayInitialize(filter,0);
      ArrayInitialize(invert,1);
      ArrayInitialize(equity,0);

      for(int n=1; n<=num_combos; n++)
        {
         equity[n-1][0]=0;
         equity[n-1][1]=n;
         variables=PORTFOLIOS[n].total;
         for(int i=0; i<variables; i++)
           {
            double lot=PORTFOLIOS[n].lot[i];
            int pointer=PORTFOLIOS[n].pointer[i];
            equity[n-1][0]+=lot*DATA[pointer].filter;
           }
        }

      if(Inversion_Mode==positive)
         for(int n=1; n<=num_combos; n++)
            if(equity[n-1][0]<0)
              {
               invert[n-1]*=-1;
               equity[n-1][0]*=-1;
               if(Print_Details)
                  Print(Portfolio_Name+": Portfolio #",n," inverted to positive");
              }

      if(Inversion_Mode==negative)
         for(int n=1; n<=num_combos; n++)
            if(equity[n-1][0]>0)
              {
               invert[n-1]*=-1;
               equity[n-1][0]*=-1;
               if(Print_Details)
                  Print(Portfolio_Name+": Portfolio #",n," inverted to negative");
              }

      ArraySort(equity);

      if(Position_Lowest==positive)
         for(int m=Lowest_From; m<=Lowest_To; m++)
           {
            int n=(int)equity[m-1][1];
            filter[n-1]=+1;
            if(Print_Details)
               Print(Portfolio_Name+": Portfolio #",n," selected as positive");
           }

      if(Position_Lowest==negative)
         for(int m=Lowest_From; m<=Lowest_To; m++)
           {
            int n=(int)equity[m-1][1];
            filter[n-1]=-1;
            if(Print_Details)
               Print(Portfolio_Name+": Portfolio #",n," selected as negative");
           }

      if(Position_Highest==positive)
         for(int m=Highest_From; m<=Highest_To; m++)
           {
            int n=(int)equity[num_combos-m][1];
            filter[n-1]=+1;
            if(Print_Details)
               Print(Portfolio_Name+": Portfolio #",n," selected as positive");
           }

      if(Position_Highest==negative)
         for(int m=Highest_From; m<=Highest_To; m++)
           {
            int n=(int)equity[num_combos-m][1];
            filter[n-1]=-1;
            if(Print_Details)
               Print(Portfolio_Name+": Portfolio #",n," selected as negative");
           }

      for(int n=1; n<=num_combos; n++)
        {
         PORTFOLIOS[n].sign=invert[n-1];
         PORTFOLIOS[n].position=filter[n-1];
        }
     }

  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CalculateSummarization()
  {

   if(error)
      return;

//---

   ArrayInitialize(PORTFOLIOS[num_total].pointer,-1);
   ArrayInitialize(PORTFOLIOS[num_total].lot,0);
   PORTFOLIOS[num_total].total=0;
   PORTFOLIOS[num_total].sign=+1;
   PORTFOLIOS[num_total].position=+1;

//---

   for(int n=1; n<=num_combos; n++)
      for(int i=0; i<num_symbols; i++)
         for(int k=0; k<MAX_SYMBOLS; k++)
           {
            int pointer=PORTFOLIOS[n].pointer[i];
            double lot=PORTFOLIOS[n].lot[i];
            double sign=PORTFOLIOS[n].sign;
            double position=PORTFOLIOS[n].position;

            if(pointer==-1)
               break;
            if(position==0)
               break;

            if(PORTFOLIOS[num_total].pointer[k]==pointer)
              {
               PORTFOLIOS[num_total].lot[k]+=lot*position*sign;
               break;
              }

            if(PORTFOLIOS[num_total].pointer[k]==-1)
              {
               PORTFOLIOS[num_total].total++;
               PORTFOLIOS[num_total].pointer[k]=pointer;
               PORTFOLIOS[num_total].lot[k]=lot*position*sign;
               break;
              }
           }

//---

   variables=0;
   string formula="";

//---

   for(int i=0; i<MAX_SYMBOLS; i++)
     {
      int pointer=PORTFOLIOS[num_total].pointer[i];
      if(pointer==-1)
         continue;

      LOTS[variables]=PORTFOLIOS[num_total].lot[i];
      SYMBOLS[variables]=DATA[pointer].symbol;
      VALUE[variables]=DATA[pointer].value;

      string lots=DoubleToString(LOTS[variables],Lots_Digits);
      formula+=SYMBOLS[variables]+CharToString(EQUAL)+lots+CharToString(SPACE);
      variables++;
     }

//---

   PORTFOLIOS[num_total].total=variables;
   if(Print_Details)
      Print(Portfolio_Name+": Summarized portfolio: ",formula);

  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CalculateScaling()
  {

   if(error)
      return;

//---

   if(Downscaling_Total)
     {
      double sum_volume=0;
      for(int n=1; n<=num_combos; n++)
         if(PORTFOLIOS[n].position!=0)
            sum_volume++;
      if(sum_volume>0)
         for(int i=0; i<variables; i++)
           {
            LOTS[i]/=sum_volume;
            PORTFOLIOS[num_total].lot[i]=LOTS[i];
           }
      else
         Alert("Empty portfolio summarization!");
      if(Print_Details)
         if(sum_volume>0)
            Print(Portfolio_Name+": Downscaling by volume: ",sum_volume);
     }

//---

   if(Portfolio_Value!=0)
     {
      double value_total=0;

      for(int i=0; i<variables; i++)
         value_total+=iClose(SYMBOLS[i],Timeframe,index_filter)*VALUE[i]*MathAbs(LOTS[i]);

      if(value_total==0)
         Alert("Zero portfolio value!");

      else
        {
         double scale_check=MathAbs(Portfolio_Value)/value_total;
         double min_diff=DBL_MAX;

         for(int m=1; m<=20; m++)
           {
            value_total=0;
            for(int i=0; i<variables; i++)
               value_total+=iClose(SYMBOLS[i],Timeframe,index_finish)*VALUE[i]*
                            NormalizeDouble(MathAbs(LOTS[i]*scale_check),Lots_Digits);

            double diff=value_total-MathAbs(Portfolio_Value);
            double abs_diff=MathAbs(diff);

            if(abs_diff<min_diff)
              {
               min_diff=abs_diff;
               scale_total=scale_check;
               scale_model=scale_check;
              }

            if(value_total==0)
               scale_check*=1.5;
            else
              {
               if(diff<0)
                  scale_check*=1.1;
               else
                  scale_check*=0.9;
              }
           }
        }

      if(Portfolio_Value<0)
        {
         scale_total*=-1;
         scale_model*=-1;
        }

      if(Print_Details)
         Print(Portfolio_Name+": Total scaling: ",scale_total);
     }

//---

   if(Portfolio_Value==0)
     {
      scale_total=Multiplicator_Total;
      scale_model=Multiplicator_Total;
      if(Print_Details)
         Print(Portfolio_Name+": Total scaling: ",scale_total);
     }

//---

   for(int n=1; n<=num_combos; n++)
      for(int i=0; i<PORTFOLIOS[n].total; i++)
         PORTFOLIOS[n].lot[i]=NormalizeDouble(PORTFOLIOS[n].lot[i]*scale_total,Lots_Digits);
   string formula="";

   for(int i=0; i<variables; i++)
     {
      LOTS[i]=NormalizeDouble(LOTS[i]*scale_total,Lots_Digits);
      PORTFOLIOS[num_total].lot[i]=LOTS[i];
      string lots=DoubleToString(LOTS[i],Lots_Digits);
      formula+=SYMBOLS[i]+CharToString(EQUAL)+lots+CharToString(SPACE);
     }

   Print(Portfolio_Name+": Finalized portfolio: ",formula);

  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void UpdateStatistics()
  {

   if(error)
      return;

//---

   double sumsq=0,count=0;
   for(int j=bar_start; j>=bar_finish; j--)
     {
      double x=BUFFERS[num_total].buffer[j];
      double m=BUFFERS[num_model].buffer[j];
      if(x==EMPTY_VALUE)
         continue;
      if(m==EMPTY_VALUE)
         m=0;
      sumsq+=MathPow(x-m,2);
      count++;
     }
   rmse=MathSqrt(sumsq/count);

//---

   double max=-DBL_MAX,min=DBL_MAX;
   for(int j=bar_start; j>=bar_finish; j--)
     {
      double x=BUFFERS[num_total].buffer[j];
      if(x==EMPTY_VALUE)
         continue;
      if(x>max)
         max=x;
      if(x<min)
         min=x;
     }
   range=max-min;
   if(range!=0)
      rmse2range=rmse/range;

//---

   sum_spread=0;
   sum_margin=0;
   sum_comms=0;
   sum_value=0;

   for(int i=0; i<variables; i++)
     {

      sum_spread+=(SymbolInfoDouble(SYMBOLS[i],SYMBOL_ASK)-SymbolInfoDouble(SYMBOLS[i],SYMBOL_BID))
                  *VALUE[i]*MathAbs(LOTS[i]);

      sum_comms+=Commission_Rate/100*VALUE[i]*iClose(SYMBOLS[i],0,0)*MathAbs(LOTS[i]);

      sum_value+=VALUE[i]*iClose(SYMBOLS[i],0,0)*MathAbs(LOTS[i]);

#ifdef __MQL4__
      sum_margin+=MarketInfo(SYMBOLS[i],MODE_MARGINREQUIRED)*MathAbs(LOTS[i]);
#else
      sum_margin+=SymbolInfoDouble(SYMBOLS[i],SYMBOL_MARGIN_INITIAL)*MathAbs(LOTS[i]);
#endif

     }

  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void DrawPortfolio(int number,bool all_bars)
  {

   if(error)
      return;

//---

   if(all_bars)
     {
      variables=PORTFOLIOS[number].total;
      ArrayInitialize(BUFFERS[number].buffer,EMPTY_VALUE);

      for(int j=draw_begin; j>=draw_end; j--)
        {
         double profit=0;
         for(int i=0; i<variables; i++)
           {
            double lot=PORTFOLIOS[number].lot[i];
            double equity=DATA[PORTFOLIOS[number].pointer[i]].data[j];
            int sign=PORTFOLIOS[number].sign;
            profit+=equity*lot*sign;
           }
         BUFFERS[number].buffer[j]=profit;
        }

      if(Realistic_Total)
         if(number==num_total)
           {
            total_shift=BUFFERS[number].buffer[bar_trading];
            for(int j=draw_begin; j>=draw_end; j--)
               BUFFERS[number].buffer[j]-=total_shift;
           }
     }

//---

   else
      if(number==num_total)
        {
         if(draw_end>0)
            return;

         //---

         if(Sync_Seconds>0)
           {
            datetime now_time=TimeCurrent();
            for(int i=0; i<variables; i++)
               if(now_time-SymbolInfoInteger(SYMBOLS[i],SYMBOL_TIME)>Sync_Seconds)
                 {
                  BUFFERS[number].buffer[0]=EMPTY_VALUE;
                  return;
                 }
           }

         //---

         double profit=0;
         for(int i=0; i<variables; i++)
           {
            string symbol=DATA[PORTFOLIOS[number].pointer[i]].symbol;
            double closing=SymbolInfoDouble(symbol,SYMBOL_BID);
            double opening=DATA[PORTFOLIOS[number].pointer[i]].opening;
            double lot=PORTFOLIOS[number].lot[i];
            profit+=(closing-opening)*VALUE[i]*lot;
           }

         //---

         BUFFERS[number].buffer[0]=profit;
         if(Realistic_Total)
            if(number==num_total)
               BUFFERS[number].buffer[0]-=total_shift;
        }

  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void DrawModel()
  {

   if(error)
      return;
   if(bar_range==0)
      return;
   ArrayInitialize(BUFFERS[num_model].buffer,EMPTY_VALUE);

//---

   for(int j=model_begin; j>=model_end; j--)
     {

      double model=0;
      if(Model_Type==fixed)
         model=0;
      if(Model_Type==spread)
         model=0;
      if(Model_Type==principal)
         model=0;
      if(Model_Type==antiprincipal)
         model=0;
      if(Model_Type==fitting)
         model=0;

      if(Model_Type==hybrid)
        {
         int bar_distance=Model_Backward?(j-bar_finish):(bar_start-j);
         double x=bar_distance/bar_range*Model_Cycles-Model_Phase;
         if(Model_Absolute)
            x=MathAbs(x);
         model=Model_Amplitude*MathSin(2*M_PI*x)+Model_Growth*x;
         model*=scale_model;
        }

      if(Model_Type==oscillator)
        {
         int bar_distance=Model_Backward?(j-bar_finish):(bar_start-j);
         double x=bar_distance/bar_range*Model_Cycles-Model_Phase;
         if(Model_Absolute)
            x=MathAbs(x);
         model=Model_Amplitude*MathSin(2*M_PI*x);
         model*=scale_model;
        }

      if(Model_Type==trend)
        {
         int bar_distance=Model_Backward?(j-bar_finish):(bar_start-j);
         double x=bar_distance/bar_range-Model_Phase;
         if(Model_Absolute)
            x=MathAbs(x);
         model=Model_Growth*x;
         model*=scale_model;
        }

      if(Model_Type==root)
        {
         int bar_distance=Model_Backward?(j-bar_finish):(bar_start-j);
         double x=bar_distance/bar_range-Model_Phase;
         int sign=(int)MathSign(x);
         if(Model_Absolute)
            sign=1;
         model=sign*Model_Growth*MathSqrt(MathAbs(x));
         model*=scale_model;
        }

      if(Model_Type==exponent)
        {
         int bar_distance=Model_Backward?(j-bar_finish):(bar_start-j);
         double x=bar_distance/bar_range*Model_Cycles-Model_Phase;
         if(Model_Absolute)
            x=MathAbs(x);
         model=Model_Growth*MathExp(x);
         model*=scale_model;
        }

      BUFFERS[num_model].buffer[j]=model;
     }

//---

   double model_shift=Model_Backward?
                      BUFFERS[num_model].buffer[bar_finish]:
                      BUFFERS[num_model].buffer[bar_start];

//---

   for(int j=model_begin; j>=model_end; j--)
      BUFFERS[num_model].buffer[j]-=model_shift;

  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void DrawIndicators(bool all_bars)
  {

   if(error)
      return;

//---

   if(!all_bars)
     {
      if(draw_end>0)
         return;
      draw_begin=0;
      draw_end=0;
     }
   else
     {
      ArrayInitialize(BUFFERS[num_main].buffer,EMPTY_VALUE);
      ArrayInitialize(BUFFERS[num_fast].buffer,EMPTY_VALUE);
      ArrayInitialize(BUFFERS[num_slow].buffer,EMPTY_VALUE);
      ArrayInitialize(BUFFERS[num_upper].buffer,EMPTY_VALUE);
      ArrayInitialize(BUFFERS[num_lower].buffer,EMPTY_VALUE);
      ArrayInitialize(BUFFERS[num_zscore].buffer,EMPTY_VALUE);
      ArrayInitialize(BUFFERS[num_macd].buffer,EMPTY_VALUE);
      ArrayInitialize(BUFFERS[num_first].buffer,EMPTY_VALUE);
     }

//---

   if(Signal_Transformation==normal)
      for(int j=draw_begin; j>=draw_end; j--)
         BUFFERS[num_first].buffer[j]=BUFFERS[num_total].buffer[j];

//---

   if(Signal_Transformation==MACD)
     {
      if(Signal_Period==0)
        {
         Alert("Zero signal period!");
         error=true;
         return;
        }

      int start_bar = all_bars ? draw_begin-(Signal_Period-1) : 0;

      for(int j=start_bar; j>=draw_end; j--)
        {
         if(BUFFERS[num_total].buffer[j]==EMPTY_VALUE)
            continue;

         double MA=0;
         for(int k=0; k<Signal_Period; k++)
            MA+=BUFFERS[num_total].buffer[j+k];

         MA/=Signal_Period;
         BUFFERS[num_first].buffer[j]=(BUFFERS[num_total].buffer[j]-MA);
        }
     }

//---

   if(Signal_Transformation==WPR)
     {
      if(Signal_Period==0)
        {
         Alert("Zero signal period!");
         error=true;
         return;
        }

      int start_bar = all_bars ? draw_begin-(Signal_Period-1) : 0;

      for(int j=start_bar; j>=draw_end; j--)
        {
         if(BUFFERS[num_total].buffer[j]==EMPTY_VALUE)
            continue;

         double max=-DBL_MAX,min=+DBL_MAX;

         for(int k=0; k<Signal_Period; k++)
           {
            if(BUFFERS[num_total].buffer[j+k]>max)
               max=BUFFERS[num_total].buffer[j+k];
            if(BUFFERS[num_total].buffer[j+k]<min)
               min=BUFFERS[num_total].buffer[j+k];
           }

         if(max-min!=0)
            BUFFERS[num_first].buffer[j]=(BUFFERS[num_total].buffer[j]-min)/(max-min);
        }
     }

//---

   if(Signal_Transformation==zscore)
     {
      if(Signal_Period==0)
        {
         Alert("Zero signal period!");
         error=true;
         return;
        }

      int start_bar = all_bars ? draw_begin-(Signal_Period-1) : 0;

      for(int j=start_bar; j>=draw_end; j--)
        {
         if(BUFFERS[num_total].buffer[j]==EMPTY_VALUE)
            continue;

         double MA=0,SD=0;
         for(int k=0; k<Signal_Period; k++)
            MA+=BUFFERS[num_total].buffer[j+k];
         MA/=Signal_Period;

         for(int k=0; k<Signal_Period; k++)
            SD+=MathPow(BUFFERS[num_total].buffer[j+k]-MA,2);
         SD=MathSqrt(SD/Signal_Period);

         if(SD!=0)
            BUFFERS[num_first].buffer[j]=(BUFFERS[num_total].buffer[j]-MA)/SD;
        }

      PlaceHorizontal("Z-level-upper-"+Portfolio_Name,+2,Signal_Color,STYLE_DOT,true,false,false);
      PlaceHorizontal("Z-level-lower-"+Portfolio_Name,-2,Signal_Color,STYLE_DOT,true,false,false);
     }

//---

   if(Main_Period>0)
     {
      int start_bar=draw_begin-(Main_Period-1);

      if(Signal_Transformation!=normal)
         start_bar-=(Signal_Period-1);

      if(!all_bars)
         start_bar=0;

      for(int j=start_bar; j>=draw_end; j--)
        {
         if(BUFFERS[num_first].buffer[j]==EMPTY_VALUE)
            continue;

         double MA=0;
         for(int k=0; k<Main_Period; k++)
            MA+=BUFFERS[num_first].buffer[j+k];

         MA/=Main_Period;
         BUFFERS[num_main].buffer[j]=MA;
        }
     }

//---

   if(Fast_Period>0)
     {
      int start_bar=draw_begin-(Fast_Period-1);

      if(Signal_Transformation!=normal)
         start_bar-=(Signal_Period-1);

      if(!all_bars)
         start_bar=0;

      for(int j=start_bar; j>=draw_end; j--)
        {
         if(BUFFERS[num_first].buffer[j]==EMPTY_VALUE)
            continue;

         double MA=0;
         for(int k=0; k<Fast_Period; k++)
            MA+=BUFFERS[num_first].buffer[j+k];

         MA/=Fast_Period;
         BUFFERS[num_fast].buffer[j]=MA;
        }
     }

//---

   if(Slow_Period>0)
     {
      int start_bar=draw_begin-(Slow_Period-1);

      if(Signal_Transformation!=normal)
         start_bar-=(Signal_Period-1);

      if(!all_bars)
         start_bar=0;

      for(int j=start_bar; j>=draw_end; j--)
        {
         if(BUFFERS[num_first].buffer[j]==EMPTY_VALUE)
            continue;

         double MA=0;
         for(int k=0; k<Slow_Period; k++)
            MA+=BUFFERS[num_first].buffer[j+k];

         MA/=Slow_Period;
         BUFFERS[num_slow].buffer[j]=MA;
        }
     }

//---

   if(Channels_Type==envelopes)
      if(Main_Period>0)
        {
         int start_bar=draw_begin-(Main_Period-1);

         if(Signal_Transformation!=normal)
            start_bar-=(Signal_Period-1);

         if(!all_bars)
            start_bar=0;

         for(int j=start_bar; j>=draw_end; j--)
           {
            if(BUFFERS[num_first].buffer[j]==EMPTY_VALUE)
               continue;
            double MA=BUFFERS[num_main].buffer[j];
            BUFFERS[num_upper].buffer[j]=MA+Channel_Size;
            BUFFERS[num_lower].buffer[j]=MA-Channel_Size;
           }
        }

//---

   if(Channels_Type==standard)
      if(Main_Period>0)
        {
         int start_bar=draw_begin-(Main_Period-1);

         if(Signal_Transformation!=normal)
            start_bar-=(Signal_Period-1);

         if(!all_bars)
            start_bar=0;

         for(int j=start_bar; j>=draw_end; j--)
           {
            if(BUFFERS[num_first].buffer[j]==EMPTY_VALUE)
               continue;
            double MA=BUFFERS[num_main].buffer[j];

            double SD=0;
            for(int k=0; k<Main_Period; k++)
               SD+=MathPow(BUFFERS[num_first].buffer[j+k]-MA,2);
            SD=MathSqrt(SD/Main_Period);

            BUFFERS[num_upper].buffer[j]=MA+SD*Channel_Size;
            BUFFERS[num_lower].buffer[j]=MA-SD*Channel_Size;
           }
        }

//---

   if(Channels_Type==transcendent)
      if(Main_Period>0)
        {
         int start_bar=draw_begin-(Main_Period-1);

         if(Signal_Transformation!=normal)
            start_bar-=(Signal_Period-1);

         if(!all_bars)
            start_bar=0;

         for(int j=start_bar; j>=draw_end; j--)
           {
            if(BUFFERS[num_first].buffer[j]==EMPTY_VALUE)
               continue;

            double MA=BUFFERS[num_main].buffer[j];
            double sum=0;

            for(int k=0; k<Main_Period-1; k++)
               sum+=MathAbs(BUFFERS[num_first].buffer[j+k]-BUFFERS[num_first].buffer[j+k+1]);
            double delta=sum/MathSqrt(Main_Period);

            BUFFERS[num_upper].buffer[j]=MA+delta*Channel_Size;
            BUFFERS[num_lower].buffer[j]=MA-delta*Channel_Size;
           }
        }

//---

   if(Channels_Type==confidence1 || Channels_Type==confidence2)
      if(all_bars)
        {
         double delta[];
         int sample=draw_begin-bar_finish;
         ArrayResize(delta,sample);

         for(int i=0; i<sample; i++)
            delta[i]=BUFFERS[num_first].buffer[bar_finish+i]-
                     BUFFERS[num_first].buffer[bar_finish+i+1];

         double mean=0;
         if(Channels_Type==confidence1)
           {
            for(int i=0; i<sample; i++)
               mean+=delta[i];
            mean/=sample;
           }

         double standard=0;
         for(int i=0; i<sample; i++)
            standard+=MathPow(delta[i]-mean,2);
         standard=MathSqrt(standard/sample);

         double b=(Signal_Transformation==normal)?BUFFERS[num_model].buffer[bar_finish]:0;

         for(int i=bar_finish; i>=draw_end; i--)
           {
            int x=bar_finish-i;
            BUFFERS[num_upper].buffer[i]=mean*x+standard*MathSqrt(x)*Channel_Size+b;
            BUFFERS[num_lower].buffer[i]=mean*x-standard*MathSqrt(x)*Channel_Size+b;
           }

         b=BUFFERS[num_model].buffer[bar_start];

         for(int i=bar_start; i<=draw_begin; i++)
           {
            int x=i-bar_start;
            BUFFERS[num_upper].buffer[i]=-mean*x+standard*MathSqrt(x)*Channel_Size+b;
            BUFFERS[num_lower].buffer[i]=-mean*x-standard*MathSqrt(x)*Channel_Size+b;
           }
        }

//---

   if(Channels_Type==corridor)
      if(!Hide_Model)
        {
         for(int j=model_begin; j>=model_end; j--)
           {
            double line=BUFFERS[num_model].buffer[j];
            BUFFERS[num_upper].buffer[j]=line+Channel_Size;
            BUFFERS[num_lower].buffer[j]=line-Channel_Size;
           }
        }

//---

   if(Channels_Type==deviation)
      if(!Hide_Model)
        {

         double sumsq=0,count=0;

         for(int j=bar_start; j>=bar_finish; j--)
           {
            double x=BUFFERS[num_total].buffer[j];
            double m=BUFFERS[num_model].buffer[j];
            if(x!=EMPTY_VALUE)
               if(m!=EMPTY_VALUE)
                 {
                  sumsq+=MathPow(x-m,2);
                  count++;
                 }
           }

         double dev=MathSqrt(sumsq/count);

         for(int j=model_begin; j>=model_end; j--)
           {
            double line=BUFFERS[num_model].buffer[j];
            BUFFERS[num_upper].buffer[j]=line+Channel_Size*dev;
            BUFFERS[num_lower].buffer[j]=line-Channel_Size*dev;
           }

        }

  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void UpdateStatus()
  {

   if(error)
      return;

   double last=BUFFERS[num_first].buffer[0];
   double prev=BUFFERS[num_first].buffer[1];

   sum_spread=0;
   for(int i=0; i<variables; i++)
      sum_spread+=(SymbolInfoDouble(SYMBOLS[i],SYMBOL_ASK)-SymbolInfoDouble(SYMBOLS[i],SYMBOL_BID))
                  *VALUE[i]*MathAbs(LOTS[i]);

   if(!Hide_Text_Data)
     {
      int line_shift=YMARGIN;
      string text=("Name: "+Portfolio_Name);
      string name=("Data-label-"+Portfolio_Name+"-1");
      PlaceLabel(name,Text_Indent+XMARGIN,line_shift,Text_Corner,text,Main_Color,FONTNAME,FONTSIZE);

      line_shift+=SPACING;
      text=("Range: "+DoubleToString(range,2)+" "+Chart_Currency);
      name=("Data-label-"+Portfolio_Name+"-2");
      PlaceLabel(name,Text_Indent+XMARGIN,line_shift,Text_Corner,text,Main_Color,FONTNAME,FONTSIZE);

      line_shift+=SPACING;
      text=("RMSE: "+DoubleToString(rmse,2)+" "+Chart_Currency);
      name=("Data-label-"+Portfolio_Name+"-3");
      PlaceLabel(name,Text_Indent+XMARGIN,line_shift,Text_Corner,text,Main_Color,FONTNAME,FONTSIZE);

      line_shift+=SPACING;
      text=("RMSE/range: "+DoubleToString(rmse2range,4));
      name=("Data-label-"+Portfolio_Name+"-4");
      PlaceLabel(name,Text_Indent+XMARGIN,line_shift,Text_Corner,text,Main_Color,FONTNAME,FONTSIZE);

      line_shift+=SPACING;
      text=("Value: "+DoubleToString(sum_value,2)+" "+Chart_Currency);
      name=("Data-label-"+Portfolio_Name+"-5");
      PlaceLabel(name,Text_Indent+XMARGIN,line_shift,Text_Corner,text,Main_Color,FONTNAME,FONTSIZE);

      line_shift+=SPACING;
      text=("Margin: "+DoubleToString(sum_margin,2)+" "+acc_currency);
      name=("Data-label-"+Portfolio_Name+"-6");
      PlaceLabel(name,Text_Indent+XMARGIN,line_shift,Text_Corner,text,Main_Color,FONTNAME,FONTSIZE);

      line_shift+=SPACING;
      text=("Commission: "+DoubleToString(sum_comms,2)+" "+Chart_Currency);
      name=("Data-label-"+Portfolio_Name+"-7");
      PlaceLabel(name,Text_Indent+XMARGIN,line_shift,Text_Corner,text,Main_Color,FONTNAME,FONTSIZE);

      line_shift+=SPACING;
      text=("Spread: "+DoubleToString(sum_spread,2)+" "+Chart_Currency);
      name=("Data-label-"+Portfolio_Name+"-8");
      PlaceLabel(name,Text_Indent+XMARGIN,line_shift,Text_Corner,text,Main_Color,FONTNAME,FONTSIZE);
     }

   if(mode_spread==longs)
     {
      ObjectDelete(chart,"Portfolio-last-"+Portfolio_Name);
      PlaceHorizontal("Portfolio-ask-"+Portfolio_Name,last+sum_spread+sum_comms,COLOR_BID_ASK,STYLE_SOLID,false,false,false);
      PlaceHorizontal("Portfolio-bid-"+Portfolio_Name,last,COLOR_BID_ASK,STYLE_SOLID,false,false,false);
     }

   if(mode_spread==shorts)
     {
      ObjectDelete(chart,"Portfolio-last-"+Portfolio_Name);
      PlaceHorizontal("Portfolio-ask-"+Portfolio_Name,last,COLOR_BID_ASK,STYLE_SOLID,false,false,false);
      PlaceHorizontal("Portfolio-bid-"+Portfolio_Name,last-sum_spread-sum_comms,COLOR_BID_ASK,STYLE_SOLID,false,false,false);
     }

   if(mode_spread==single)
     {
      ObjectDelete(chart,"Portfolio-bid-"+Portfolio_Name);
      ObjectDelete(chart,"Portfolio-last-"+Portfolio_Name);
      PlaceHorizontal("Portfolio-last-"+Portfolio_Name,last,COLOR_BID_ASK,STYLE_SOLID,false,false,false);
     }

   if(mode_spread==none)
     {
      ObjectDelete(chart,"Portfolio-ask-"+Portfolio_Name);
      ObjectDelete(chart,"Portfolio-bid-"+Portfolio_Name);
      ObjectDelete(chart,"Portfolio-last-"+Portfolio_Name);
     }

   GlobalVariableSet("Portfolio-"+Portfolio_Name,last);
   GlobalVariableSet("Quality-"+Portfolio_Name,rmse2range);

   if(!Hide_Model)
      GlobalVariableSet("Model-"+Portfolio_Name,BUFFERS[num_model].buffer[0]);
   if(Main_Period>0)
      GlobalVariableSet("Main-"+Portfolio_Name,BUFFERS[num_main].buffer[0]);
   if(Fast_Period>0)
      GlobalVariableSet("Fast-"+Portfolio_Name,BUFFERS[num_fast].buffer[0]);
   if(Slow_Period>0)
      GlobalVariableSet("Slow-"+Portfolio_Name,BUFFERS[num_slow].buffer[0]);

   if(Channels_Type!=empty)
     {
      GlobalVariableSet("Upper-"+Portfolio_Name,BUFFERS[num_upper].buffer[0]);
      GlobalVariableSet("Lower-"+Portfolio_Name,BUFFERS[num_lower].buffer[0]);
     }

  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double ContractValue(string symbol,datetime time,ENUM_TIMEFRAMES period,string currency)
  {
   double value=SymbolInfoDouble(symbol,SYMBOL_TRADE_CONTRACT_SIZE);
   string quote=SymbolInfoString(symbol,SYMBOL_CURRENCY_PROFIT);
   if(value==0)
      value=1;

   if(quote!="USD")
     {
      string direct=(FX_Prefix+quote+"USD"+FX_Postfix);
      if(SymbolInfoDouble(direct,SYMBOL_POINT)!=0)
        {
         int shift=iBarShift(direct,period,time);
         double price=iClose(direct,period,shift);
         if(price>0)
            value*=price;
        }
      else
        {
         string indirect=FX_Prefix+"USD"+quote+FX_Postfix;
         int shift=iBarShift(indirect,period,time);
         double price=iClose(indirect,period,shift);
         if(price>0)
            value/=price;
        }
     }

   if(currency!="USD")
     {
      string direct=(FX_Prefix+currency+"USD"+FX_Postfix);
      if(SymbolInfoDouble(direct,SYMBOL_POINT)!=0)
        {
         int shift=iBarShift(direct,period,time);
         double price=iClose(direct,period,shift);
         if(price>0)
            value/=price;
        }
      else
        {
         string indirect=(FX_Prefix+"USD"+currency+FX_Postfix);
         int shift=iBarShift(indirect,period,time);
         double price=iClose(indirect,period,shift);
         if(price>0)
            value*=price;
        }
     }

   return(value);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void UpdateFormula()
  {
   if(!Hide_Text_Data)
      for(int i=0,c=0; i<variables; i++)
         if(!Hide_Zero_Lots || LOTS[i]!=0)
           {
            c++;

            string text=SYMBOLS[i]+
                        CharToString(EQUAL)+
                        (LOTS[i]>=0 ? "+" : "-")+
                        DoubleToString(MathAbs(LOTS[i]),Lots_Digits);

            string name="Formula-label-"+Portfolio_Name+"-"+(string)(i+1);

            PlaceLabel(name,Text_Indent+XMARGIN,YMARGIN+(c+8)*SPACING,
                       Text_Corner,text,Main_Color,FONTNAME,FONTSIZE);

            if(LOTS[i]==0)
               continue;

            double minlot=SymbolInfoDouble(SYMBOLS[i],SYMBOL_VOLUME_MIN);

            if(MathAbs(LOTS[i])<minlot)
               Alert("Minimum trading lot ",minlot," violated for: ",text);
           }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void HideByFilter()
  {
   if(Hide_By_Filter)
      for(int n=1; n<=num_combos; n++)
         if(PORTFOLIOS[n].position==0)
            ArrayInitialize(BUFFERS[n].buffer,EMPTY_VALUE);
   if(mode_stream)
      for(int n=1; n<=num_combos; n++)
         ArrayInitialize(BUFFERS[n].buffer,EMPTY_VALUE);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void DrawChartGrid()
  {
   if(Chart_Grid_Size==0)
      return;

   color colour=(color)ChartGetInteger(chart,CHART_COLOR_GRID,window);

   double max=-DBL_MAX,min=DBL_MAX;
   for(int j=Bars(_Symbol,_Period)-1; j>=0; j--)
      for(int n=0; n<dim_size; n++)
        {
         double X=BUFFERS[n].buffer[j];
         if(X==EMPTY_VALUE)
            continue;
         if(X>max)
            max=X;
         if(X<min)
            min=X;
        }

   double level=0;

   while(level<max)
     {
      level+=Chart_Grid_Size;
      string name="Grid-level-"+Portfolio_Name+":"+DoubleToString(level,2);
      PlaceHorizontal(name,level,colour,STYLE_DOT,true,false,false);
     }

   level=0;

   while(level>min)
     {
      level-=Chart_Grid_Size;
      string name="Grid-level-"+Portfolio_Name+":"+DoubleToString(level,2);
      PlaceHorizontal(name,level,colour,STYLE_DOT,true,false,false);
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void PlaceLabel(string name,int x,int y,int corner,string text,int colour,string font,int size)
  {
   ENUM_ANCHOR_POINT anchor=0;
   if(corner==CORNER_LEFT_LOWER)
      anchor=ANCHOR_LEFT_LOWER;
   else
      if(corner==CORNER_LEFT_UPPER)
         anchor=ANCHOR_LEFT_UPPER;
      else
         if(corner==CORNER_RIGHT_LOWER)
            anchor=ANCHOR_RIGHT_LOWER;
         else
            if(corner==CORNER_RIGHT_UPPER)
               anchor=ANCHOR_RIGHT_UPPER;

   ObjectCreate(chart,name,OBJ_LABEL,window,0,0);
   ObjectSetInteger(chart,name,OBJPROP_CORNER,corner);
   ObjectSetInteger(chart,name,OBJPROP_ANCHOR,anchor);
   ObjectSetInteger(chart,name,OBJPROP_XDISTANCE,x);
   ObjectSetInteger(chart,name,OBJPROP_YDISTANCE,y);
   ObjectSetString(chart,name,OBJPROP_TEXT,text);
   ObjectSetString(chart,name,OBJPROP_FONT,font);
   ObjectSetInteger(chart,name,OBJPROP_FONTSIZE,size);
   ObjectSetInteger(chart,name,OBJPROP_COLOR,colour);
   ObjectSetInteger(chart,name,OBJPROP_SELECTABLE,false);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void PlaceVertical(string name,datetime time,int colour,int style,bool back,bool selectable,bool selected)
  {
   ObjectCreate(chart,name,OBJ_VLINE,window,time,0);
   ObjectSetInteger(chart,name,OBJPROP_TIME,time);
   ObjectSetInteger(chart,name,OBJPROP_COLOR,colour);
   ObjectSetInteger(chart,name,OBJPROP_STYLE,style);
   ObjectSetInteger(chart,name,OBJPROP_BACK,back);
   ObjectSetInteger(chart,name,OBJPROP_SELECTABLE,selectable);
   ObjectSetInteger(chart,name,OBJPROP_SELECTED,selected);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void PlaceHorizontal(string name,double price,int colour,int style,bool back,bool selectable,bool selected)
  {
   ObjectCreate(chart,name,OBJ_HLINE,window,0,price);
   ObjectSetDouble(chart,name,OBJPROP_PRICE,price);
   ObjectSetInteger(chart,name,OBJPROP_COLOR,colour);
   ObjectSetInteger(chart,name,OBJPROP_STYLE,style);
   ObjectSetInteger(chart,name,OBJPROP_BACK,back);
   ObjectSetInteger(chart,name,OBJPROP_SELECTABLE,selectable);
   ObjectSetInteger(chart,name,OBJPROP_SELECTED,selected);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void ExportCSV()
  {

   if(error)
      return;
   if(CSV_Export_File=="")
      return;

   string working_name=CSV_Export_File+".csv";
   PrepareFile(working_name);

   for(int j=draw_begin; j>=draw_end; j--)
     {
      string text=TimeToString(iTime(_Symbol,_Period,j));

      for(int n=1; n<=num_combos; n++)
        {
         double value=BUFFERS[n].buffer[j];
         if(value==EMPTY_VALUE)
            continue;
         text=(text+CSV_Separator+DoubleToString(value,2));
        }

      double value=BUFFERS[num_total].buffer[j];
      if(value==EMPTY_VALUE)
         continue;

      text=(text+CSV_Separator+DoubleToString(value,2));
      WriteLine(working_name,text);
     }

   Alert("CSV data export completed.");

  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void PrepareFile(string file)
  {
   int handle=FileOpen(file,FILE_WRITE,CSV_Separator);
   if(handle==-1)
     {
      Alert("Error opening export file!");
      error=true;
      return;
     }
   FileClose(handle);
   string text="DATE/TIME";
   for(int n=1; n<=num_combos; n++)
      text+=(CSV_Separator+"PORTFOLIO #"+string(n));
   text+=(CSV_Separator+"TOTAL PORTFOLIO");
   WriteLine(file,text);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void WriteLine(string file,string text)
  {
   int handle=FileOpen(file,FILE_READ|FILE_WRITE,CSV_Separator);
   if(handle==-1)
      return;
   FileSeek(handle,0,SEEK_END);
   FileWrite(handle,text);
   FileClose(handle);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
#ifdef __MQL4__
void PrepareOHLC()
  {

   if(error)
      return;
   if(!OHLC_mode)
      return;

   if(Data_Timeframe>_Period)
     {
      Alert("Incorrect aggregation timeframe!");
      error=true;
      return;
     }

   string name=(_Symbol+(string)Chart_Timeframe+".hst");

   OHLC_handle=-1;
   OHLC_handle=FileOpenHistory(name,FILE_BIN|FILE_WRITE|FILE_ANSI);
   FileClose(OHLC_handle);

   OHLC_handle=-1;
   OHLC_handle=FileOpenHistory(name,FILE_BIN|FILE_READ|FILE_WRITE|FILE_SHARE_WRITE|FILE_SHARE_READ|FILE_ANSI);

   if(OHLC_handle<0)
     {
      Alert("Error opening OHLC history file!");
      error=true;
      return;
     }

   int data_unused[13];
   FileWriteInteger(OHLC_handle,401,LONG_VALUE);
   FileWriteString(OHLC_handle,"",64);
   FileWriteString(OHLC_handle,_Symbol,12);
   FileWriteInteger(OHLC_handle,Chart_Timeframe,LONG_VALUE);
   FileWriteInteger(OHLC_handle,2,LONG_VALUE);
   FileWriteInteger(OHLC_handle,0,LONG_VALUE);
   FileWriteInteger(OHLC_handle,0,LONG_VALUE);
   FileWriteArray(OHLC_handle,data_unused,0,13);

  }
#endif
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
#ifdef __MQL4__
void GenerateOHLC(bool all_bars)
  {

   if(error)
      return;
   if(!OHLC_mode)
      return;

   MqlRates rates;

   int SHIFTS[];
   double OPENINGS[];
   ArrayResize(OPENINGS,variables);
   ArrayResize(SHIFTS,variables);

   for(int i=0; i<variables; i++)
      OPENINGS[i]=DATA[PORTFOLIOS[num_total].pointer[i]].opening;

   int subbars=int(_Period/Data_Timeframe);

   if(!all_bars)
      FileSeek(OHLC_handle,file_position,SEEK_SET);

   for(int j=draw_begin; j>=draw_end; j--)
     {
      double bar_open=0,bar_high=0,bar_low=0,bar_close=0;

      for(int k=0; k<subbars; k++)
        {
         datetime time_x=Time[j]+k*60*Data_Timeframe;
         bool missing=false;
         for(int i=0; i<variables; i++)
           {
            SHIFTS[i]=iBarShift(SYMBOLS[i],Data_Timeframe,time_x,true);
            if(SHIFTS[i]==-1)
               missing=true;
           }
         if(missing)
            continue;

         double sum_open=0,sum_high=0,sum_low=0,sum_close=0;
         for(int i=0; i<variables; i++)
           {
            double value=ContractValue(SYMBOLS[i],time_x,Data_Timeframe,Chart_Currency);
            double open =iOpen(SYMBOLS[i],Data_Timeframe,SHIFTS[i]);
            double close=iClose(SYMBOLS[i],Data_Timeframe,SHIFTS[i]);
            double high =iHigh(SYMBOLS[i],Data_Timeframe,SHIFTS[i]);
            double low  =iLow(SYMBOLS[i],Data_Timeframe,SHIFTS[i]);
            sum_close+=(close-OPENINGS[i])*value*LOTS[i];
            sum_open +=(open -OPENINGS[i])*value*LOTS[i];
            if(LOTS[i]>0)
               sum_high += (high -OPENINGS[i]) *value*LOTS[i];
            else
               sum_low  += (high -OPENINGS[i]) *value*LOTS[i];
            if(LOTS[i]>0)
               sum_low  += (low  -OPENINGS[i]) *value*LOTS[i];
            else
               sum_high += (low  -OPENINGS[i]) *value*LOTS[i];
           }

         if(bar_high==0)
            bar_high=sum_high;
         if(sum_high>bar_high)
            bar_high=sum_high;
         if(bar_low==0)
            bar_low=sum_low;
         if(sum_low<bar_low)
            bar_low=sum_low;
         if(bar_open==0)
            bar_open=sum_open;
         bar_close=sum_close;
        }

      file_position=FileTell(OHLC_handle);
      rates.time =Time[j];
      rates.open =NormalizeDouble(bar_open+Price_Start,2);
      rates.high =NormalizeDouble(bar_high+Price_Start,2);
      rates.low  =NormalizeDouble(bar_low+Price_Start,2);
      rates.close=NormalizeDouble(bar_close+Price_Start,2);
      FileWriteStruct(OHLC_handle,rates);
     }

   FileFlush(OHLC_handle);

  }
#endif
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
#ifdef __MQL4__
void FindOHLC()
  {

   long currChart,prevChart=ChartFirst();

   if(ChartSymbol(prevChart)==_Symbol)
      if(ChartPeriod(prevChart)==Chart_Timeframe)
        {
         OHLC_chart=prevChart;
         return;
        }

      else
        {

         int i=0,limit=100;
         while(i<limit)
           {
            currChart=ChartNext(prevChart);

            if(ChartSymbol(currChart)==_Symbol)
               if(ChartPeriod(currChart)==Chart_Timeframe)
                 {
                  OHLC_chart=currChart;
                  return;
                 }

            if(currChart<0)
               break;
            prevChart=currChart;
            i++;
           }

        }

  }
#endif
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
#ifdef __MQL4__
void RefreshOHLC(bool all_bars)
  {

   if(error)
      return;

   if(!OHLC_mode)
      return;

   if(OHLC_chart<=0)
     {
      OHLC_chart=ChartOpen(_Symbol,Chart_Timeframe);
      GlobalVariableSet("OHLC_"+Portfolio_Name,OHLC_chart);
     }

   if(all_bars)
     {

      ObjectDelete(OHLC_chart,"Start");
      ObjectDelete(OHLC_chart,"Finish");
      ObjectDelete(OHLC_chart,"Filter");

      ObjectCreate(OHLC_chart,"Start",OBJ_VLINE,0,time_start,0);
      ObjectCreate(OHLC_chart,"Finish",OBJ_VLINE,0,time_finish,0);
      ObjectCreate(OHLC_chart,"Filter",OBJ_VLINE,0,time_filter,0);

      ObjectSetInteger(OHLC_chart,"Start",OBJPROP_STYLE,STYLE_DASH);
      ObjectSetInteger(OHLC_chart,"Finish",OBJPROP_STYLE,STYLE_DASH);
      ObjectSetInteger(OHLC_chart,"Filter",OBJPROP_STYLE,STYLE_DOT);

      ObjectSetInteger(OHLC_chart,"Start",OBJPROP_COLOR,COLOR_INTERVAL);
      ObjectSetInteger(OHLC_chart,"Finish",OBJPROP_COLOR,COLOR_INTERVAL);
      ObjectSetInteger(OHLC_chart,"Filter",OBJPROP_COLOR,COLOR_FILTER);

      ObjectSetInteger(OHLC_chart,"Start",OBJPROP_SELECTABLE,false);
      ObjectSetInteger(OHLC_chart,"Finish",OBJPROP_SELECTABLE,false);
      ObjectSetInteger(OHLC_chart,"Filter",OBJPROP_SELECTABLE,false);

      ObjectSetInteger(OHLC_chart,"Start",OBJPROP_BACK,true);
      ObjectSetInteger(OHLC_chart,"Finish",OBJPROP_BACK,true);
      ObjectSetInteger(OHLC_chart,"Filter",OBJPROP_BACK,true);

      ObjectSetString(OHLC_chart,"Start",OBJPROP_TEXT,TimeToString(time_start));
      ObjectSetString(OHLC_chart,"Finish",OBJPROP_TEXT,TimeToString(time_finish));
      ObjectSetString(OHLC_chart,"Filter",OBJPROP_TEXT,TimeToString(time_filter));

      int anchor=0;
      if(Text_Corner==CORNER_LEFT_LOWER)
         anchor=ANCHOR_LEFT_LOWER;
      else
         if(Text_Corner==CORNER_LEFT_UPPER)
            anchor=ANCHOR_LEFT_UPPER;
         else
            if(Text_Corner==CORNER_RIGHT_LOWER)
               anchor=ANCHOR_RIGHT_LOWER;
            else
               if(Text_Corner==CORNER_RIGHT_UPPER)
                  anchor=ANCHOR_RIGHT_UPPER;
      string label="Portfolio: "+Portfolio_Name;

      ObjectCreate(OHLC_chart,"Name",OBJ_LABEL,0,0,0);
      ObjectSetString(OHLC_chart,"Name",OBJPROP_TEXT,label);
      ObjectSetString(OHLC_chart,"Name",OBJPROP_FONT,FONTNAME);
      ObjectSetInteger(OHLC_chart,"Name",OBJPROP_FONTSIZE,FONTSIZE*2);
      ObjectSetInteger(OHLC_chart,"Name",OBJPROP_COLOR,ChartGetInteger(OHLC_chart,CHART_COLOR_GRID));
      ObjectSetInteger(OHLC_chart,"Name",OBJPROP_CORNER,Text_Corner);
      ObjectSetInteger(OHLC_chart,"Name",OBJPROP_ANCHOR,anchor);
      ObjectSetInteger(OHLC_chart,"Name",OBJPROP_XDISTANCE,XMARGIN);
      ObjectSetInteger(OHLC_chart,"Name",OBJPROP_YDISTANCE,YMARGIN);
      ObjectSetInteger(OHLC_chart,"Name",OBJPROP_SELECTABLE,false);
      ObjectSetInteger(OHLC_chart,"Name",OBJPROP_BACK,true);

     }

   ChartSetSymbolPeriod(OHLC_chart,_Symbol,Chart_Timeframe);

  }
#endif
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void SetupCombinations()
  {

   for(int i=0; i<MAX_LINES; i++)
      COMBINATIONS[i]="";

//---

   if(Generation_Type==formula)
     {
      if(Portfolio_Formula=="")
        {
         Alert("Empty portfolio formula!");
         error=true;
         return;
        }
      COMBINATIONS[01]=Portfolio_Formula;
      num_combos=1;
      num_symbols=MAX_SYMBOLS;
     }

//---

   if(Generation_Type==decomposition)
     {
      string names[];
      int portfolios=StringSplit(Portfolio_Formula,SPACE,names);
      for(int n=1; n<=portfolios; n++)
         COMBINATIONS[n]=names[n-1];
      num_combos=portfolios;
      num_symbols=1;
     }

//---

   if(Generation_Type==import)
     {
      int handle=FileOpen(Import_File,FILE_READ|FILE_ANSI,CSV_Separator);
      if(handle==-1)
        {
         Alert("Error opening import file!");
         error=true;
         return;
        }
      FileSeek(handle,0,SEEK_SET);
      int portfolios=0;
      while(!FileIsEnding(handle))
        {
         portfolios++;
         string text=FileReadString(handle);
         COMBINATIONS[portfolios]=text;
        }
      FileClose(handle);
      num_combos=portfolios;
      num_symbols=MAX_SYMBOLS;
     }

//---

   if(Generation_Type==consolidation)
     {
      string names[];
      int portfolios=StringSplit(Portfolio_Formula,SPACE,names);
      for(int n=1; n<=portfolios; n++)
        {
         int counter=0;
         for(int k=1; k<=MAX_SYMBOLS; k++)
           {
            string name="Formula-label-"+names[n-1]+"-"+IntegerToString(k);
            if(ObjectFind(chart,name)<0)
               continue;
            COMBINATIONS[n]+=(CharToString(SPACE)+ObjectGetString(chart,name,OBJPROP_TEXT));
            counter++;
           }
         if(counter<1)
           {
            Alert("Portfolio not found: "+names[n-1]);
            saved_time=0;
           }
        }
      num_combos=portfolios;
      num_symbols=MAX_SYMBOLS;
     }

//---

   if(Generation_Type==terminal)
     {
#ifdef __MQL4__
      int total=OrdersTotal();
      if(total>MAX_SYMBOLS)
        {
         Alert("Too many orders: only ",MAX_SYMBOLS," will be used!");
         total=MAX_SYMBOLS;
        }
      for(int i=0; i<total; i++)
        {
         if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
            continue;
         if(Portfolio_Formula!="")
            if(StringFind(OrderComment(),Portfolio_Formula)==-1)
               continue;
         string symbol=OrderSymbol();
         double lots=OrderLots();
         string volume=DoubleToString(lots,Lots_Digits);
         int type=OrderType();
         if(type==OP_BUY)
            COMBINATIONS[01]+=symbol+CharToString(EQUAL)+"+"+volume+CharToString(SPACE);
         if(type==OP_SELL)
            COMBINATIONS[01]+=symbol+CharToString(EQUAL)+"-"+volume+CharToString(SPACE);
        }
#else
      int total=PositionsTotal();
      if(total>MAX_SYMBOLS)
        {
         Alert("Too many positions: only ",MAX_SYMBOLS," will be used!");
         total=MAX_SYMBOLS;
        }
      for(int i=0; i<total; i++)
        {
         if(!PositionSelectByTicket(PositionGetTicket(i)))
            continue;
         if(Portfolio_Formula!="")
            if(StringFind(PositionGetString(POSITION_COMMENT),Portfolio_Formula)==-1)
               continue;
         string symbol=PositionGetString(POSITION_SYMBOL);
         double lots=PositionGetDouble(POSITION_VOLUME);
         string volume=DoubleToString(lots,Lots_Digits);
         long type=PositionGetInteger(POSITION_TYPE);
         if(type==POSITION_TYPE_BUY)
            COMBINATIONS[01]+=symbol+CharToString(EQUAL)+"+"+volume+CharToString(SPACE);
         if(type==POSITION_TYPE_SELL)
            COMBINATIONS[01]+=symbol+CharToString(EQUAL)+"-"+volume+CharToString(SPACE);
        }
#endif
      num_combos=1;
      num_symbols=total;
     }

//---

   if(Generation_Type==basic28)
     {
      COMBINATIONS[01]="AUDCAD";
      COMBINATIONS[02]="AUDCHF";
      COMBINATIONS[03]="AUDJPY";
      COMBINATIONS[04]="AUDNZD";
      COMBINATIONS[05]="AUDUSD";
      COMBINATIONS[06]="CADCHF";
      COMBINATIONS[07]="CADJPY";
      COMBINATIONS[08]="CHFJPY";
      COMBINATIONS[09]="EURAUD";
      COMBINATIONS[10]="EURCAD";
      COMBINATIONS[11]="EURCHF";
      COMBINATIONS[12]="EURGBP";
      COMBINATIONS[13]="EURJPY";
      COMBINATIONS[14]="EURNZD";
      COMBINATIONS[15]="EURUSD";
      COMBINATIONS[16]="GBPAUD";
      COMBINATIONS[17]="GBPCAD";
      COMBINATIONS[18]="GBPCHF";
      COMBINATIONS[19]="GBPJPY";
      COMBINATIONS[20]="GBPNZD";
      COMBINATIONS[21]="GBPUSD";
      COMBINATIONS[22]="NZDCAD";
      COMBINATIONS[23]="NZDCHF";
      COMBINATIONS[24]="NZDJPY";
      COMBINATIONS[25]="NZDUSD";
      COMBINATIONS[26]="USDCAD";
      COMBINATIONS[27]="USDCHF";
      COMBINATIONS[28]="USDJPY";
      num_combos=28;
      num_symbols=1;
     }

//---

   if(Generation_Type==fours35)
     {
      COMBINATIONS[01]="USDJPY GBPUSD NZDUSD USDCHF";
      COMBINATIONS[02]="USDCAD GBPUSD NZDUSD USDCHF";
      COMBINATIONS[03]="AUDUSD GBPUSD NZDUSD USDCHF";
      COMBINATIONS[04]="EURUSD GBPUSD NZDUSD USDCHF";
      COMBINATIONS[05]="USDCAD USDJPY NZDUSD USDCHF";
      COMBINATIONS[06]="AUDUSD USDJPY NZDUSD USDCHF";
      COMBINATIONS[07]="EURUSD USDJPY NZDUSD USDCHF";
      COMBINATIONS[08]="AUDUSD USDCAD NZDUSD USDCHF";
      COMBINATIONS[09]="EURUSD USDCAD NZDUSD USDCHF";
      COMBINATIONS[10]="EURUSD AUDUSD NZDUSD USDCHF";
      COMBINATIONS[11]="USDCAD USDJPY GBPUSD USDCHF";
      COMBINATIONS[12]="AUDUSD USDJPY GBPUSD USDCHF";
      COMBINATIONS[13]="EURUSD USDJPY GBPUSD USDCHF";
      COMBINATIONS[14]="AUDUSD USDCAD GBPUSD USDCHF";
      COMBINATIONS[15]="EURUSD USDCAD GBPUSD USDCHF";
      COMBINATIONS[16]="EURUSD AUDUSD GBPUSD USDCHF";
      COMBINATIONS[17]="AUDUSD USDCAD USDJPY USDCHF";
      COMBINATIONS[18]="EURUSD USDCAD USDJPY USDCHF";
      COMBINATIONS[19]="EURUSD AUDUSD USDJPY USDCHF";
      COMBINATIONS[20]="EURUSD AUDUSD USDCAD USDCHF";
      COMBINATIONS[21]="USDCAD USDJPY GBPUSD NZDUSD";
      COMBINATIONS[22]="AUDUSD USDJPY GBPUSD NZDUSD";
      COMBINATIONS[23]="EURUSD USDJPY GBPUSD NZDUSD";
      COMBINATIONS[24]="AUDUSD USDCAD GBPUSD NZDUSD";
      COMBINATIONS[25]="EURUSD USDCAD GBPUSD NZDUSD";
      COMBINATIONS[26]="EURUSD AUDUSD GBPUSD NZDUSD";
      COMBINATIONS[27]="AUDUSD USDCAD USDJPY NZDUSD";
      COMBINATIONS[28]="EURUSD USDCAD USDJPY NZDUSD";
      COMBINATIONS[29]="EURUSD AUDUSD USDJPY NZDUSD";
      COMBINATIONS[30]="EURUSD AUDUSD USDCAD NZDUSD";
      COMBINATIONS[31]="AUDUSD USDCAD USDJPY GBPUSD";
      COMBINATIONS[32]="EURUSD USDCAD USDJPY GBPUSD";
      COMBINATIONS[33]="EURUSD AUDUSD USDJPY GBPUSD";
      COMBINATIONS[34]="EURUSD AUDUSD USDCAD GBPUSD";
      COMBINATIONS[35]="EURUSD AUDUSD USDCAD USDJPY";
      num_combos=35;
      num_symbols=4;
     }

//---

   if(Generation_Type==threes35)
     {
      COMBINATIONS[01]="EURUSD GBPUSD AUDUSD";
      COMBINATIONS[02]="EURUSD GBPUSD NZDUSD";
      COMBINATIONS[03]="EURUSD GBPUSD USDJPY";
      COMBINATIONS[04]="EURUSD GBPUSD USDCAD";
      COMBINATIONS[05]="EURUSD GBPUSD USDCHF";
      COMBINATIONS[06]="EURUSD AUDUSD NZDUSD";
      COMBINATIONS[07]="EURUSD AUDUSD USDJPY";
      COMBINATIONS[08]="EURUSD AUDUSD USDCAD";
      COMBINATIONS[09]="EURUSD AUDUSD USDCHF";
      COMBINATIONS[10]="EURUSD NZDUSD USDJPY";
      COMBINATIONS[11]="EURUSD NZDUSD USDCAD";
      COMBINATIONS[12]="EURUSD NZDUSD USDCHF";
      COMBINATIONS[13]="EURUSD USDJPY USDCAD";
      COMBINATIONS[14]="EURUSD USDJPY USDCHF";
      COMBINATIONS[15]="EURUSD USDCAD USDCHF";
      COMBINATIONS[16]="GBPUSD AUDUSD NZDUSD";
      COMBINATIONS[17]="GBPUSD AUDUSD USDJPY";
      COMBINATIONS[18]="GBPUSD AUDUSD USDCAD";
      COMBINATIONS[19]="GBPUSD AUDUSD USDCHF";
      COMBINATIONS[20]="GBPUSD NZDUSD USDJPY";
      COMBINATIONS[21]="GBPUSD NZDUSD USDCAD";
      COMBINATIONS[22]="GBPUSD NZDUSD USDCHF";
      COMBINATIONS[23]="GBPUSD USDJPY USDCAD";
      COMBINATIONS[24]="GBPUSD USDJPY USDCHF";
      COMBINATIONS[25]="GBPUSD USDCAD USDCHF";
      COMBINATIONS[26]="AUDUSD NZDUSD USDJPY";
      COMBINATIONS[27]="AUDUSD NZDUSD USDCAD";
      COMBINATIONS[28]="AUDUSD NZDUSD USDCHF";
      COMBINATIONS[29]="AUDUSD USDJPY USDCAD";
      COMBINATIONS[30]="AUDUSD USDJPY USDCHF";
      COMBINATIONS[31]="AUDUSD USDCAD USDCHF";
      COMBINATIONS[32]="NZDUSD USDJPY USDCAD";
      COMBINATIONS[33]="NZDUSD USDJPY USDCHF";
      COMBINATIONS[34]="NZDUSD USDCAD USDCHF";
      COMBINATIONS[35]="USDJPY USDCAD USDCHF";
      num_combos=35;
      num_symbols=3;
     }

//---

   if(Generation_Type==fours105)
     {
      COMBINATIONS[1]="AUDCAD CHFJPY EURGBP NZDUSD";
      COMBINATIONS[2]="AUDCAD CHFJPY EURNZD GBPUSD";
      COMBINATIONS[3]="AUDCAD CHFJPY EURUSD GBPNZD";
      COMBINATIONS[4]="AUDCAD EURCHF GBPJPY NZDUSD";
      COMBINATIONS[5]="AUDCAD EURCHF GBPNZD USDJPY";
      COMBINATIONS[6]="AUDCAD EURCHF GBPUSD NZDJPY";
      COMBINATIONS[7]="AUDCAD EURGBP NZDCHF USDJPY";
      COMBINATIONS[8]="AUDCAD EURGBP NZDJPY USDCHF";
      COMBINATIONS[9]="AUDCAD EURJPY GBPCHF NZDUSD";
      COMBINATIONS[10]="AUDCAD EURJPY GBPNZD USDCHF";
      COMBINATIONS[11]="AUDCAD EURJPY GBPUSD NZDCHF";
      COMBINATIONS[12]="AUDCAD EURNZD GBPCHF USDJPY";
      COMBINATIONS[13]="AUDCAD EURNZD GBPJPY USDCHF";
      COMBINATIONS[14]="AUDCAD EURUSD GBPCHF NZDJPY";
      COMBINATIONS[15]="AUDCAD EURUSD GBPJPY NZDCHF";
      COMBINATIONS[16]="AUDCHF CADJPY EURGBP NZDUSD";
      COMBINATIONS[17]="AUDCHF CADJPY EURNZD GBPUSD";
      COMBINATIONS[18]="AUDCHF CADJPY EURUSD GBPNZD";
      COMBINATIONS[19]="AUDCHF EURCAD GBPJPY NZDUSD";
      COMBINATIONS[20]="AUDCHF EURCAD GBPNZD USDJPY";
      COMBINATIONS[21]="AUDCHF EURCAD GBPUSD NZDJPY";
      COMBINATIONS[22]="AUDCHF EURGBP NZDCAD USDJPY";
      COMBINATIONS[23]="AUDCHF EURGBP NZDJPY USDCAD";
      COMBINATIONS[24]="AUDCHF EURJPY GBPCAD NZDUSD";
      COMBINATIONS[25]="AUDCHF EURJPY GBPNZD USDCAD";
      COMBINATIONS[26]="AUDCHF EURJPY GBPUSD NZDCAD";
      COMBINATIONS[27]="AUDCHF EURNZD GBPCAD USDJPY";
      COMBINATIONS[28]="AUDCHF EURNZD GBPJPY USDCAD";
      COMBINATIONS[29]="AUDCHF EURUSD GBPCAD NZDJPY";
      COMBINATIONS[30]="AUDCHF EURUSD GBPJPY NZDCAD";
      COMBINATIONS[31]="AUDJPY CADCHF EURGBP NZDUSD";
      COMBINATIONS[32]="AUDJPY CADCHF EURNZD GBPUSD";
      COMBINATIONS[33]="AUDJPY CADCHF EURUSD GBPNZD";
      COMBINATIONS[34]="AUDJPY EURCAD GBPCHF NZDUSD";
      COMBINATIONS[35]="AUDJPY EURCAD GBPNZD USDCHF";
      COMBINATIONS[36]="AUDJPY EURCAD GBPUSD NZDCHF";
      COMBINATIONS[37]="AUDJPY EURCHF GBPCAD NZDUSD";
      COMBINATIONS[38]="AUDJPY EURCHF GBPNZD USDCAD";
      COMBINATIONS[39]="AUDJPY EURCHF GBPUSD NZDCAD";
      COMBINATIONS[40]="AUDJPY EURGBP NZDCAD USDCHF";
      COMBINATIONS[41]="AUDJPY EURGBP NZDCHF USDCAD";
      COMBINATIONS[42]="AUDJPY EURNZD GBPCAD USDCHF";
      COMBINATIONS[43]="AUDJPY EURNZD GBPCHF USDCAD";
      COMBINATIONS[44]="AUDJPY EURUSD GBPCAD NZDCHF";
      COMBINATIONS[45]="AUDJPY EURUSD GBPCHF NZDCAD";
      COMBINATIONS[46]="AUDNZD CADCHF EURGBP USDJPY";
      COMBINATIONS[47]="AUDNZD CADCHF EURJPY GBPUSD";
      COMBINATIONS[48]="AUDNZD CADCHF EURUSD GBPJPY";
      COMBINATIONS[49]="AUDNZD CADJPY EURCHF GBPUSD";
      COMBINATIONS[50]="AUDNZD CADJPY EURGBP USDCHF";
      COMBINATIONS[51]="AUDNZD CADJPY EURUSD GBPCHF";
      COMBINATIONS[52]="AUDNZD CHFJPY EURCAD GBPUSD";
      COMBINATIONS[53]="AUDNZD CHFJPY EURGBP USDCAD";
      COMBINATIONS[54]="AUDNZD CHFJPY EURUSD GBPCAD";
      COMBINATIONS[55]="AUDNZD EURCAD GBPCHF USDJPY";
      COMBINATIONS[56]="AUDNZD EURCAD GBPJPY USDCHF";
      COMBINATIONS[57]="AUDNZD EURCHF GBPCAD USDJPY";
      COMBINATIONS[58]="AUDNZD EURCHF GBPJPY USDCAD";
      COMBINATIONS[59]="AUDNZD EURJPY GBPCAD USDCHF";
      COMBINATIONS[60]="AUDNZD EURJPY GBPCHF USDCAD";
      COMBINATIONS[61]="AUDUSD CADCHF EURGBP NZDJPY";
      COMBINATIONS[62]="AUDUSD CADCHF EURJPY GBPNZD";
      COMBINATIONS[63]="AUDUSD CADCHF EURNZD GBPJPY";
      COMBINATIONS[64]="AUDUSD CADJPY EURCHF GBPNZD";
      COMBINATIONS[65]="AUDUSD CADJPY EURGBP NZDCHF";
      COMBINATIONS[66]="AUDUSD CADJPY EURNZD GBPCHF";
      COMBINATIONS[67]="AUDUSD CHFJPY EURCAD GBPNZD";
      COMBINATIONS[68]="AUDUSD CHFJPY EURGBP NZDCAD";
      COMBINATIONS[69]="AUDUSD CHFJPY EURNZD GBPCAD";
      COMBINATIONS[70]="AUDUSD EURCAD GBPCHF NZDJPY";
      COMBINATIONS[71]="AUDUSD EURCAD GBPJPY NZDCHF";
      COMBINATIONS[72]="AUDUSD EURCHF GBPCAD NZDJPY";
      COMBINATIONS[73]="AUDUSD EURCHF GBPJPY NZDCAD";
      COMBINATIONS[74]="AUDUSD EURJPY GBPCAD NZDCHF";
      COMBINATIONS[75]="AUDUSD EURJPY GBPCHF NZDCAD";
      COMBINATIONS[76]="CADCHF EURAUD GBPJPY NZDUSD";
      COMBINATIONS[77]="CADCHF EURAUD GBPNZD USDJPY";
      COMBINATIONS[78]="CADCHF EURAUD GBPUSD NZDJPY";
      COMBINATIONS[79]="CADCHF EURJPY GBPAUD NZDUSD";
      COMBINATIONS[80]="CADCHF EURNZD GBPAUD USDJPY";
      COMBINATIONS[81]="CADCHF EURUSD GBPAUD NZDJPY";
      COMBINATIONS[82]="CADJPY EURAUD GBPCHF NZDUSD";
      COMBINATIONS[83]="CADJPY EURAUD GBPNZD USDCHF";
      COMBINATIONS[84]="CADJPY EURAUD GBPUSD NZDCHF";
      COMBINATIONS[85]="CADJPY EURCHF GBPAUD NZDUSD";
      COMBINATIONS[86]="CADJPY EURNZD GBPAUD USDCHF";
      COMBINATIONS[87]="CADJPY EURUSD GBPAUD NZDCHF";
      COMBINATIONS[88]="CHFJPY EURAUD GBPCAD NZDUSD";
      COMBINATIONS[89]="CHFJPY EURAUD GBPNZD USDCAD";
      COMBINATIONS[90]="CHFJPY EURAUD GBPUSD NZDCAD";
      COMBINATIONS[91]="CHFJPY EURCAD GBPAUD NZDUSD";
      COMBINATIONS[92]="CHFJPY EURNZD GBPAUD USDCAD";
      COMBINATIONS[93]="CHFJPY EURUSD GBPAUD NZDCAD";
      COMBINATIONS[94]="EURAUD GBPCAD NZDCHF USDJPY";
      COMBINATIONS[95]="EURAUD GBPCAD NZDJPY USDCHF";
      COMBINATIONS[96]="EURAUD GBPCHF NZDCAD USDJPY";
      COMBINATIONS[97]="EURAUD GBPCHF NZDJPY USDCAD";
      COMBINATIONS[98]="EURAUD GBPJPY NZDCAD USDCHF";
      COMBINATIONS[99]="EURAUD GBPJPY NZDCHF USDCAD";
      COMBINATIONS[100]="EURCAD GBPAUD NZDCHF USDJPY";
      COMBINATIONS[101]="EURCAD GBPAUD NZDJPY USDCHF";
      COMBINATIONS[102]="EURCHF GBPAUD NZDCAD USDJPY";
      COMBINATIONS[103]="EURCHF GBPAUD NZDJPY USDCAD";
      COMBINATIONS[104]="EURJPY GBPAUD NZDCAD USDCHF";
      COMBINATIONS[105]="EURJPY GBPAUD NZDCHF USDCAD";
      num_combos=105;
      num_symbols=4;
     }

//---

   if(Generation_Type==threes420)
     {
      COMBINATIONS[1]="AUDCAD CHFJPY EURGBP";
      COMBINATIONS[2]="AUDCAD CHFJPY EURNZD";
      COMBINATIONS[3]="AUDCAD CHFJPY EURUSD";
      COMBINATIONS[4]="AUDCAD CHFJPY GBPNZD";
      COMBINATIONS[5]="AUDCAD CHFJPY GBPUSD";
      COMBINATIONS[6]="AUDCAD CHFJPY NZDUSD";
      COMBINATIONS[7]="AUDCAD EURCHF GBPJPY";
      COMBINATIONS[8]="AUDCAD EURCHF GBPNZD";
      COMBINATIONS[9]="AUDCAD EURCHF GBPUSD";
      COMBINATIONS[10]="AUDCAD EURCHF NZDJPY";
      COMBINATIONS[11]="AUDCAD EURCHF NZDUSD";
      COMBINATIONS[12]="AUDCAD EURCHF USDJPY";
      COMBINATIONS[13]="AUDCAD EURGBP NZDCHF";
      COMBINATIONS[14]="AUDCAD EURGBP NZDJPY";
      COMBINATIONS[15]="AUDCAD EURGBP NZDUSD";
      COMBINATIONS[16]="AUDCAD EURGBP USDCHF";
      COMBINATIONS[17]="AUDCAD EURGBP USDJPY";
      COMBINATIONS[18]="AUDCAD EURJPY GBPCHF";
      COMBINATIONS[19]="AUDCAD EURJPY GBPNZD";
      COMBINATIONS[20]="AUDCAD EURJPY GBPUSD";
      COMBINATIONS[21]="AUDCAD EURJPY NZDCHF";
      COMBINATIONS[22]="AUDCAD EURJPY NZDUSD";
      COMBINATIONS[23]="AUDCAD EURJPY USDCHF";
      COMBINATIONS[24]="AUDCAD EURNZD GBPCHF";
      COMBINATIONS[25]="AUDCAD EURNZD GBPJPY";
      COMBINATIONS[26]="AUDCAD EURNZD GBPUSD";
      COMBINATIONS[27]="AUDCAD EURNZD USDCHF";
      COMBINATIONS[28]="AUDCAD EURNZD USDJPY";
      COMBINATIONS[29]="AUDCAD EURUSD GBPCHF";
      COMBINATIONS[30]="AUDCAD EURUSD GBPJPY";
      COMBINATIONS[31]="AUDCAD EURUSD GBPNZD";
      COMBINATIONS[32]="AUDCAD EURUSD NZDCHF";
      COMBINATIONS[33]="AUDCAD EURUSD NZDJPY";
      COMBINATIONS[34]="AUDCAD GBPCHF NZDJPY";
      COMBINATIONS[35]="AUDCAD GBPCHF NZDUSD";
      COMBINATIONS[36]="AUDCAD GBPCHF USDJPY";
      COMBINATIONS[37]="AUDCAD GBPJPY NZDCHF";
      COMBINATIONS[38]="AUDCAD GBPJPY NZDUSD";
      COMBINATIONS[39]="AUDCAD GBPJPY USDCHF";
      COMBINATIONS[40]="AUDCAD GBPNZD USDCHF";
      COMBINATIONS[41]="AUDCAD GBPNZD USDJPY";
      COMBINATIONS[42]="AUDCAD GBPUSD NZDCHF";
      COMBINATIONS[43]="AUDCAD GBPUSD NZDJPY";
      COMBINATIONS[44]="AUDCAD NZDCHF USDJPY";
      COMBINATIONS[45]="AUDCAD NZDJPY USDCHF";
      COMBINATIONS[46]="AUDCHF CADJPY EURGBP";
      COMBINATIONS[47]="AUDCHF CADJPY EURNZD";
      COMBINATIONS[48]="AUDCHF CADJPY EURUSD";
      COMBINATIONS[49]="AUDCHF CADJPY GBPNZD";
      COMBINATIONS[50]="AUDCHF CADJPY GBPUSD";
      COMBINATIONS[51]="AUDCHF CADJPY NZDUSD";
      COMBINATIONS[52]="AUDCHF EURCAD GBPJPY";
      COMBINATIONS[53]="AUDCHF EURCAD GBPNZD";
      COMBINATIONS[54]="AUDCHF EURCAD GBPUSD";
      COMBINATIONS[55]="AUDCHF EURCAD NZDJPY";
      COMBINATIONS[56]="AUDCHF EURCAD NZDUSD";
      COMBINATIONS[57]="AUDCHF EURCAD USDJPY";
      COMBINATIONS[58]="AUDCHF EURGBP NZDCAD";
      COMBINATIONS[59]="AUDCHF EURGBP NZDJPY";
      COMBINATIONS[60]="AUDCHF EURGBP NZDUSD";
      COMBINATIONS[61]="AUDCHF EURGBP USDCAD";
      COMBINATIONS[62]="AUDCHF EURGBP USDJPY";
      COMBINATIONS[63]="AUDCHF EURJPY GBPCAD";
      COMBINATIONS[64]="AUDCHF EURJPY GBPNZD";
      COMBINATIONS[65]="AUDCHF EURJPY GBPUSD";
      COMBINATIONS[66]="AUDCHF EURJPY NZDCAD";
      COMBINATIONS[67]="AUDCHF EURJPY NZDUSD";
      COMBINATIONS[68]="AUDCHF EURJPY USDCAD";
      COMBINATIONS[69]="AUDCHF EURNZD GBPCAD";
      COMBINATIONS[70]="AUDCHF EURNZD GBPJPY";
      COMBINATIONS[71]="AUDCHF EURNZD GBPUSD";
      COMBINATIONS[72]="AUDCHF EURNZD USDCAD";
      COMBINATIONS[73]="AUDCHF EURNZD USDJPY";
      COMBINATIONS[74]="AUDCHF EURUSD GBPCAD";
      COMBINATIONS[75]="AUDCHF EURUSD GBPJPY";
      COMBINATIONS[76]="AUDCHF EURUSD GBPNZD";
      COMBINATIONS[77]="AUDCHF EURUSD NZDCAD";
      COMBINATIONS[78]="AUDCHF EURUSD NZDJPY";
      COMBINATIONS[79]="AUDCHF GBPCAD NZDJPY";
      COMBINATIONS[80]="AUDCHF GBPCAD NZDUSD";
      COMBINATIONS[81]="AUDCHF GBPCAD USDJPY";
      COMBINATIONS[82]="AUDCHF GBPJPY NZDCAD";
      COMBINATIONS[83]="AUDCHF GBPJPY NZDUSD";
      COMBINATIONS[84]="AUDCHF GBPJPY USDCAD";
      COMBINATIONS[85]="AUDCHF GBPNZD USDCAD";
      COMBINATIONS[86]="AUDCHF GBPNZD USDJPY";
      COMBINATIONS[87]="AUDCHF GBPUSD NZDCAD";
      COMBINATIONS[88]="AUDCHF GBPUSD NZDJPY";
      COMBINATIONS[89]="AUDCHF NZDCAD USDJPY";
      COMBINATIONS[90]="AUDCHF NZDJPY USDCAD";
      COMBINATIONS[91]="AUDJPY CADCHF EURGBP";
      COMBINATIONS[92]="AUDJPY CADCHF EURNZD";
      COMBINATIONS[93]="AUDJPY CADCHF EURUSD";
      COMBINATIONS[94]="AUDJPY CADCHF GBPNZD";
      COMBINATIONS[95]="AUDJPY CADCHF GBPUSD";
      COMBINATIONS[96]="AUDJPY CADCHF NZDUSD";
      COMBINATIONS[97]="AUDJPY EURCAD GBPCHF";
      COMBINATIONS[98]="AUDJPY EURCAD GBPNZD";
      COMBINATIONS[99]="AUDJPY EURCAD GBPUSD";
      COMBINATIONS[100]="AUDJPY EURCAD NZDCHF";
      COMBINATIONS[101]="AUDJPY EURCAD NZDUSD";
      COMBINATIONS[102]="AUDJPY EURCAD USDCHF";
      COMBINATIONS[103]="AUDJPY EURCHF GBPCAD";
      COMBINATIONS[104]="AUDJPY EURCHF GBPNZD";
      COMBINATIONS[105]="AUDJPY EURCHF GBPUSD";
      COMBINATIONS[106]="AUDJPY EURCHF NZDCAD";
      COMBINATIONS[107]="AUDJPY EURCHF NZDUSD";
      COMBINATIONS[108]="AUDJPY EURCHF USDCAD";
      COMBINATIONS[109]="AUDJPY EURGBP NZDCAD";
      COMBINATIONS[110]="AUDJPY EURGBP NZDCHF";
      COMBINATIONS[111]="AUDJPY EURGBP NZDUSD";
      COMBINATIONS[112]="AUDJPY EURGBP USDCAD";
      COMBINATIONS[113]="AUDJPY EURGBP USDCHF";
      COMBINATIONS[114]="AUDJPY EURNZD GBPCAD";
      COMBINATIONS[115]="AUDJPY EURNZD GBPCHF";
      COMBINATIONS[116]="AUDJPY EURNZD GBPUSD";
      COMBINATIONS[117]="AUDJPY EURNZD USDCAD";
      COMBINATIONS[118]="AUDJPY EURNZD USDCHF";
      COMBINATIONS[119]="AUDJPY EURUSD GBPCAD";
      COMBINATIONS[120]="AUDJPY EURUSD GBPCHF";
      COMBINATIONS[121]="AUDJPY EURUSD GBPNZD";
      COMBINATIONS[122]="AUDJPY EURUSD NZDCAD";
      COMBINATIONS[123]="AUDJPY EURUSD NZDCHF";
      COMBINATIONS[124]="AUDJPY GBPCAD NZDCHF";
      COMBINATIONS[125]="AUDJPY GBPCAD NZDUSD";
      COMBINATIONS[126]="AUDJPY GBPCAD USDCHF";
      COMBINATIONS[127]="AUDJPY GBPCHF NZDCAD";
      COMBINATIONS[128]="AUDJPY GBPCHF NZDUSD";
      COMBINATIONS[129]="AUDJPY GBPCHF USDCAD";
      COMBINATIONS[130]="AUDJPY GBPNZD USDCAD";
      COMBINATIONS[131]="AUDJPY GBPNZD USDCHF";
      COMBINATIONS[132]="AUDJPY GBPUSD NZDCAD";
      COMBINATIONS[133]="AUDJPY GBPUSD NZDCHF";
      COMBINATIONS[134]="AUDJPY NZDCAD USDCHF";
      COMBINATIONS[135]="AUDJPY NZDCHF USDCAD";
      COMBINATIONS[136]="AUDNZD CADCHF EURGBP";
      COMBINATIONS[137]="AUDNZD CADCHF EURJPY";
      COMBINATIONS[138]="AUDNZD CADCHF EURUSD";
      COMBINATIONS[139]="AUDNZD CADCHF GBPJPY";
      COMBINATIONS[140]="AUDNZD CADCHF GBPUSD";
      COMBINATIONS[141]="AUDNZD CADCHF USDJPY";
      COMBINATIONS[142]="AUDNZD CADJPY EURCHF";
      COMBINATIONS[143]="AUDNZD CADJPY EURGBP";
      COMBINATIONS[144]="AUDNZD CADJPY EURUSD";
      COMBINATIONS[145]="AUDNZD CADJPY GBPCHF";
      COMBINATIONS[146]="AUDNZD CADJPY GBPUSD";
      COMBINATIONS[147]="AUDNZD CADJPY USDCHF";
      COMBINATIONS[148]="AUDNZD CHFJPY EURCAD";
      COMBINATIONS[149]="AUDNZD CHFJPY EURGBP";
      COMBINATIONS[150]="AUDNZD CHFJPY EURUSD";
      COMBINATIONS[151]="AUDNZD CHFJPY GBPCAD";
      COMBINATIONS[152]="AUDNZD CHFJPY GBPUSD";
      COMBINATIONS[153]="AUDNZD CHFJPY USDCAD";
      COMBINATIONS[154]="AUDNZD EURCAD GBPCHF";
      COMBINATIONS[155]="AUDNZD EURCAD GBPJPY";
      COMBINATIONS[156]="AUDNZD EURCAD GBPUSD";
      COMBINATIONS[157]="AUDNZD EURCAD USDCHF";
      COMBINATIONS[158]="AUDNZD EURCAD USDJPY";
      COMBINATIONS[159]="AUDNZD EURCHF GBPCAD";
      COMBINATIONS[160]="AUDNZD EURCHF GBPJPY";
      COMBINATIONS[161]="AUDNZD EURCHF GBPUSD";
      COMBINATIONS[162]="AUDNZD EURCHF USDCAD";
      COMBINATIONS[163]="AUDNZD EURCHF USDJPY";
      COMBINATIONS[164]="AUDNZD EURGBP USDCAD";
      COMBINATIONS[165]="AUDNZD EURGBP USDCHF";
      COMBINATIONS[166]="AUDNZD EURGBP USDJPY";
      COMBINATIONS[167]="AUDNZD EURJPY GBPCAD";
      COMBINATIONS[168]="AUDNZD EURJPY GBPCHF";
      COMBINATIONS[169]="AUDNZD EURJPY GBPUSD";
      COMBINATIONS[170]="AUDNZD EURJPY USDCAD";
      COMBINATIONS[171]="AUDNZD EURJPY USDCHF";
      COMBINATIONS[172]="AUDNZD EURUSD GBPCAD";
      COMBINATIONS[173]="AUDNZD EURUSD GBPCHF";
      COMBINATIONS[174]="AUDNZD EURUSD GBPJPY";
      COMBINATIONS[175]="AUDNZD GBPCAD USDCHF";
      COMBINATIONS[176]="AUDNZD GBPCAD USDJPY";
      COMBINATIONS[177]="AUDNZD GBPCHF USDCAD";
      COMBINATIONS[178]="AUDNZD GBPCHF USDJPY";
      COMBINATIONS[179]="AUDNZD GBPJPY USDCAD";
      COMBINATIONS[180]="AUDNZD GBPJPY USDCHF";
      COMBINATIONS[181]="AUDUSD CADCHF EURGBP";
      COMBINATIONS[182]="AUDUSD CADCHF EURJPY";
      COMBINATIONS[183]="AUDUSD CADCHF EURNZD";
      COMBINATIONS[184]="AUDUSD CADCHF GBPJPY";
      COMBINATIONS[185]="AUDUSD CADCHF GBPNZD";
      COMBINATIONS[186]="AUDUSD CADCHF NZDJPY";
      COMBINATIONS[187]="AUDUSD CADJPY EURCHF";
      COMBINATIONS[188]="AUDUSD CADJPY EURGBP";
      COMBINATIONS[189]="AUDUSD CADJPY EURNZD";
      COMBINATIONS[190]="AUDUSD CADJPY GBPCHF";
      COMBINATIONS[191]="AUDUSD CADJPY GBPNZD";
      COMBINATIONS[192]="AUDUSD CADJPY NZDCHF";
      COMBINATIONS[193]="AUDUSD CHFJPY EURCAD";
      COMBINATIONS[194]="AUDUSD CHFJPY EURGBP";
      COMBINATIONS[195]="AUDUSD CHFJPY EURNZD";
      COMBINATIONS[196]="AUDUSD CHFJPY GBPCAD";
      COMBINATIONS[197]="AUDUSD CHFJPY GBPNZD";
      COMBINATIONS[198]="AUDUSD CHFJPY NZDCAD";
      COMBINATIONS[199]="AUDUSD EURCAD GBPCHF";
      COMBINATIONS[200]="AUDUSD EURCAD GBPJPY";
      COMBINATIONS[201]="AUDUSD EURCAD GBPNZD";
      COMBINATIONS[202]="AUDUSD EURCAD NZDCHF";
      COMBINATIONS[203]="AUDUSD EURCAD NZDJPY";
      COMBINATIONS[204]="AUDUSD EURCHF GBPCAD";
      COMBINATIONS[205]="AUDUSD EURCHF GBPJPY";
      COMBINATIONS[206]="AUDUSD EURCHF GBPNZD";
      COMBINATIONS[207]="AUDUSD EURCHF NZDCAD";
      COMBINATIONS[208]="AUDUSD EURCHF NZDJPY";
      COMBINATIONS[209]="AUDUSD EURGBP NZDCAD";
      COMBINATIONS[210]="AUDUSD EURGBP NZDCHF";
      COMBINATIONS[211]="AUDUSD EURGBP NZDJPY";
      COMBINATIONS[212]="AUDUSD EURJPY GBPCAD";
      COMBINATIONS[213]="AUDUSD EURJPY GBPCHF";
      COMBINATIONS[214]="AUDUSD EURJPY GBPNZD";
      COMBINATIONS[215]="AUDUSD EURJPY NZDCAD";
      COMBINATIONS[216]="AUDUSD EURJPY NZDCHF";
      COMBINATIONS[217]="AUDUSD EURNZD GBPCAD";
      COMBINATIONS[218]="AUDUSD EURNZD GBPCHF";
      COMBINATIONS[219]="AUDUSD EURNZD GBPJPY";
      COMBINATIONS[220]="AUDUSD GBPCAD NZDCHF";
      COMBINATIONS[221]="AUDUSD GBPCAD NZDJPY";
      COMBINATIONS[222]="AUDUSD GBPCHF NZDCAD";
      COMBINATIONS[223]="AUDUSD GBPCHF NZDJPY";
      COMBINATIONS[224]="AUDUSD GBPJPY NZDCAD";
      COMBINATIONS[225]="AUDUSD GBPJPY NZDCHF";
      COMBINATIONS[226]="CADCHF EURAUD GBPJPY";
      COMBINATIONS[227]="CADCHF EURAUD GBPNZD";
      COMBINATIONS[228]="CADCHF EURAUD GBPUSD";
      COMBINATIONS[229]="CADCHF EURAUD NZDJPY";
      COMBINATIONS[230]="CADCHF EURAUD NZDUSD";
      COMBINATIONS[231]="CADCHF EURAUD USDJPY";
      COMBINATIONS[232]="CADCHF EURGBP NZDJPY";
      COMBINATIONS[233]="CADCHF EURGBP NZDUSD";
      COMBINATIONS[234]="CADCHF EURGBP USDJPY";
      COMBINATIONS[235]="CADCHF EURJPY GBPAUD";
      COMBINATIONS[236]="CADCHF EURJPY GBPNZD";
      COMBINATIONS[237]="CADCHF EURJPY GBPUSD";
      COMBINATIONS[238]="CADCHF EURJPY NZDUSD";
      COMBINATIONS[239]="CADCHF EURNZD GBPAUD";
      COMBINATIONS[240]="CADCHF EURNZD GBPJPY";
      COMBINATIONS[241]="CADCHF EURNZD GBPUSD";
      COMBINATIONS[242]="CADCHF EURNZD USDJPY";
      COMBINATIONS[243]="CADCHF EURUSD GBPAUD";
      COMBINATIONS[244]="CADCHF EURUSD GBPJPY";
      COMBINATIONS[245]="CADCHF EURUSD GBPNZD";
      COMBINATIONS[246]="CADCHF EURUSD NZDJPY";
      COMBINATIONS[247]="CADCHF GBPAUD NZDJPY";
      COMBINATIONS[248]="CADCHF GBPAUD NZDUSD";
      COMBINATIONS[249]="CADCHF GBPAUD USDJPY";
      COMBINATIONS[250]="CADCHF GBPJPY NZDUSD";
      COMBINATIONS[251]="CADCHF GBPNZD USDJPY";
      COMBINATIONS[252]="CADCHF GBPUSD NZDJPY";
      COMBINATIONS[253]="CADJPY EURAUD GBPCHF";
      COMBINATIONS[254]="CADJPY EURAUD GBPNZD";
      COMBINATIONS[255]="CADJPY EURAUD GBPUSD";
      COMBINATIONS[256]="CADJPY EURAUD NZDCHF";
      COMBINATIONS[257]="CADJPY EURAUD NZDUSD";
      COMBINATIONS[258]="CADJPY EURAUD USDCHF";
      COMBINATIONS[259]="CADJPY EURCHF GBPAUD";
      COMBINATIONS[260]="CADJPY EURCHF GBPNZD";
      COMBINATIONS[261]="CADJPY EURCHF GBPUSD";
      COMBINATIONS[262]="CADJPY EURCHF NZDUSD";
      COMBINATIONS[263]="CADJPY EURGBP NZDCHF";
      COMBINATIONS[264]="CADJPY EURGBP NZDUSD";
      COMBINATIONS[265]="CADJPY EURGBP USDCHF";
      COMBINATIONS[266]="CADJPY EURNZD GBPAUD";
      COMBINATIONS[267]="CADJPY EURNZD GBPCHF";
      COMBINATIONS[268]="CADJPY EURNZD GBPUSD";
      COMBINATIONS[269]="CADJPY EURNZD USDCHF";
      COMBINATIONS[270]="CADJPY EURUSD GBPAUD";
      COMBINATIONS[271]="CADJPY EURUSD GBPCHF";
      COMBINATIONS[272]="CADJPY EURUSD GBPNZD";
      COMBINATIONS[273]="CADJPY EURUSD NZDCHF";
      COMBINATIONS[274]="CADJPY GBPAUD NZDCHF";
      COMBINATIONS[275]="CADJPY GBPAUD NZDUSD";
      COMBINATIONS[276]="CADJPY GBPAUD USDCHF";
      COMBINATIONS[277]="CADJPY GBPCHF NZDUSD";
      COMBINATIONS[278]="CADJPY GBPNZD USDCHF";
      COMBINATIONS[279]="CADJPY GBPUSD NZDCHF";
      COMBINATIONS[280]="CHFJPY EURAUD GBPCAD";
      COMBINATIONS[281]="CHFJPY EURAUD GBPNZD";
      COMBINATIONS[282]="CHFJPY EURAUD GBPUSD";
      COMBINATIONS[283]="CHFJPY EURAUD NZDCAD";
      COMBINATIONS[284]="CHFJPY EURAUD NZDUSD";
      COMBINATIONS[285]="CHFJPY EURAUD USDCAD";
      COMBINATIONS[286]="CHFJPY EURCAD GBPAUD";
      COMBINATIONS[287]="CHFJPY EURCAD GBPNZD";
      COMBINATIONS[288]="CHFJPY EURCAD GBPUSD";
      COMBINATIONS[289]="CHFJPY EURCAD NZDUSD";
      COMBINATIONS[290]="CHFJPY EURGBP NZDCAD";
      COMBINATIONS[291]="CHFJPY EURGBP NZDUSD";
      COMBINATIONS[292]="CHFJPY EURGBP USDCAD";
      COMBINATIONS[293]="CHFJPY EURNZD GBPAUD";
      COMBINATIONS[294]="CHFJPY EURNZD GBPCAD";
      COMBINATIONS[295]="CHFJPY EURNZD GBPUSD";
      COMBINATIONS[296]="CHFJPY EURNZD USDCAD";
      COMBINATIONS[297]="CHFJPY EURUSD GBPAUD";
      COMBINATIONS[298]="CHFJPY EURUSD GBPCAD";
      COMBINATIONS[299]="CHFJPY EURUSD GBPNZD";
      COMBINATIONS[300]="CHFJPY EURUSD NZDCAD";
      COMBINATIONS[301]="CHFJPY GBPAUD NZDCAD";
      COMBINATIONS[302]="CHFJPY GBPAUD NZDUSD";
      COMBINATIONS[303]="CHFJPY GBPAUD USDCAD";
      COMBINATIONS[304]="CHFJPY GBPCAD NZDUSD";
      COMBINATIONS[305]="CHFJPY GBPNZD USDCAD";
      COMBINATIONS[306]="CHFJPY GBPUSD NZDCAD";
      COMBINATIONS[307]="EURAUD GBPCAD NZDCHF";
      COMBINATIONS[308]="EURAUD GBPCAD NZDJPY";
      COMBINATIONS[309]="EURAUD GBPCAD NZDUSD";
      COMBINATIONS[310]="EURAUD GBPCAD USDCHF";
      COMBINATIONS[311]="EURAUD GBPCAD USDJPY";
      COMBINATIONS[312]="EURAUD GBPCHF NZDCAD";
      COMBINATIONS[313]="EURAUD GBPCHF NZDJPY";
      COMBINATIONS[314]="EURAUD GBPCHF NZDUSD";
      COMBINATIONS[315]="EURAUD GBPCHF USDCAD";
      COMBINATIONS[316]="EURAUD GBPCHF USDJPY";
      COMBINATIONS[317]="EURAUD GBPJPY NZDCAD";
      COMBINATIONS[318]="EURAUD GBPJPY NZDCHF";
      COMBINATIONS[319]="EURAUD GBPJPY NZDUSD";
      COMBINATIONS[320]="EURAUD GBPJPY USDCAD";
      COMBINATIONS[321]="EURAUD GBPJPY USDCHF";
      COMBINATIONS[322]="EURAUD GBPNZD USDCAD";
      COMBINATIONS[323]="EURAUD GBPNZD USDCHF";
      COMBINATIONS[324]="EURAUD GBPNZD USDJPY";
      COMBINATIONS[325]="EURAUD GBPUSD NZDCAD";
      COMBINATIONS[326]="EURAUD GBPUSD NZDCHF";
      COMBINATIONS[327]="EURAUD GBPUSD NZDJPY";
      COMBINATIONS[328]="EURAUD NZDCAD USDCHF";
      COMBINATIONS[329]="EURAUD NZDCAD USDJPY";
      COMBINATIONS[330]="EURAUD NZDCHF USDCAD";
      COMBINATIONS[331]="EURAUD NZDCHF USDJPY";
      COMBINATIONS[332]="EURAUD NZDJPY USDCAD";
      COMBINATIONS[333]="EURAUD NZDJPY USDCHF";
      COMBINATIONS[334]="EURCAD GBPAUD NZDCHF";
      COMBINATIONS[335]="EURCAD GBPAUD NZDJPY";
      COMBINATIONS[336]="EURCAD GBPAUD NZDUSD";
      COMBINATIONS[337]="EURCAD GBPAUD USDCHF";
      COMBINATIONS[338]="EURCAD GBPAUD USDJPY";
      COMBINATIONS[339]="EURCAD GBPCHF NZDJPY";
      COMBINATIONS[340]="EURCAD GBPCHF NZDUSD";
      COMBINATIONS[341]="EURCAD GBPCHF USDJPY";
      COMBINATIONS[342]="EURCAD GBPJPY NZDCHF";
      COMBINATIONS[343]="EURCAD GBPJPY NZDUSD";
      COMBINATIONS[344]="EURCAD GBPJPY USDCHF";
      COMBINATIONS[345]="EURCAD GBPNZD USDCHF";
      COMBINATIONS[346]="EURCAD GBPNZD USDJPY";
      COMBINATIONS[347]="EURCAD GBPUSD NZDCHF";
      COMBINATIONS[348]="EURCAD GBPUSD NZDJPY";
      COMBINATIONS[349]="EURCAD NZDCHF USDJPY";
      COMBINATIONS[350]="EURCAD NZDJPY USDCHF";
      COMBINATIONS[351]="EURCHF GBPAUD NZDCAD";
      COMBINATIONS[352]="EURCHF GBPAUD NZDJPY";
      COMBINATIONS[353]="EURCHF GBPAUD NZDUSD";
      COMBINATIONS[354]="EURCHF GBPAUD USDCAD";
      COMBINATIONS[355]="EURCHF GBPAUD USDJPY";
      COMBINATIONS[356]="EURCHF GBPCAD NZDJPY";
      COMBINATIONS[357]="EURCHF GBPCAD NZDUSD";
      COMBINATIONS[358]="EURCHF GBPCAD USDJPY";
      COMBINATIONS[359]="EURCHF GBPJPY NZDCAD";
      COMBINATIONS[360]="EURCHF GBPJPY NZDUSD";
      COMBINATIONS[361]="EURCHF GBPJPY USDCAD";
      COMBINATIONS[362]="EURCHF GBPNZD USDCAD";
      COMBINATIONS[363]="EURCHF GBPNZD USDJPY";
      COMBINATIONS[364]="EURCHF GBPUSD NZDCAD";
      COMBINATIONS[365]="EURCHF GBPUSD NZDJPY";
      COMBINATIONS[366]="EURCHF NZDCAD USDJPY";
      COMBINATIONS[367]="EURCHF NZDJPY USDCAD";
      COMBINATIONS[368]="EURGBP NZDCAD USDCHF";
      COMBINATIONS[369]="EURGBP NZDCAD USDJPY";
      COMBINATIONS[370]="EURGBP NZDCHF USDCAD";
      COMBINATIONS[371]="EURGBP NZDCHF USDJPY";
      COMBINATIONS[372]="EURGBP NZDJPY USDCAD";
      COMBINATIONS[373]="EURGBP NZDJPY USDCHF";
      COMBINATIONS[374]="EURJPY GBPAUD NZDCAD";
      COMBINATIONS[375]="EURJPY GBPAUD NZDCHF";
      COMBINATIONS[376]="EURJPY GBPAUD NZDUSD";
      COMBINATIONS[377]="EURJPY GBPAUD USDCAD";
      COMBINATIONS[378]="EURJPY GBPAUD USDCHF";
      COMBINATIONS[379]="EURJPY GBPCAD NZDCHF";
      COMBINATIONS[380]="EURJPY GBPCAD NZDUSD";
      COMBINATIONS[381]="EURJPY GBPCAD USDCHF";
      COMBINATIONS[382]="EURJPY GBPCHF NZDCAD";
      COMBINATIONS[383]="EURJPY GBPCHF NZDUSD";
      COMBINATIONS[384]="EURJPY GBPCHF USDCAD";
      COMBINATIONS[385]="EURJPY GBPNZD USDCAD";
      COMBINATIONS[386]="EURJPY GBPNZD USDCHF";
      COMBINATIONS[387]="EURJPY GBPUSD NZDCAD";
      COMBINATIONS[388]="EURJPY GBPUSD NZDCHF";
      COMBINATIONS[389]="EURJPY NZDCAD USDCHF";
      COMBINATIONS[390]="EURJPY NZDCHF USDCAD";
      COMBINATIONS[391]="EURNZD GBPAUD USDCAD";
      COMBINATIONS[392]="EURNZD GBPAUD USDCHF";
      COMBINATIONS[393]="EURNZD GBPAUD USDJPY";
      COMBINATIONS[394]="EURNZD GBPCAD USDCHF";
      COMBINATIONS[395]="EURNZD GBPCAD USDJPY";
      COMBINATIONS[396]="EURNZD GBPCHF USDCAD";
      COMBINATIONS[397]="EURNZD GBPCHF USDJPY";
      COMBINATIONS[398]="EURNZD GBPJPY USDCAD";
      COMBINATIONS[399]="EURNZD GBPJPY USDCHF";
      COMBINATIONS[400]="EURUSD GBPAUD NZDCAD";
      COMBINATIONS[401]="EURUSD GBPAUD NZDCHF";
      COMBINATIONS[402]="EURUSD GBPAUD NZDJPY";
      COMBINATIONS[403]="EURUSD GBPCAD NZDCHF";
      COMBINATIONS[404]="EURUSD GBPCAD NZDJPY";
      COMBINATIONS[405]="EURUSD GBPCHF NZDCAD";
      COMBINATIONS[406]="EURUSD GBPCHF NZDJPY";
      COMBINATIONS[407]="EURUSD GBPJPY NZDCAD";
      COMBINATIONS[408]="EURUSD GBPJPY NZDCHF";
      COMBINATIONS[409]="GBPAUD NZDCAD USDCHF";
      COMBINATIONS[410]="GBPAUD NZDCAD USDJPY";
      COMBINATIONS[411]="GBPAUD NZDCHF USDCAD";
      COMBINATIONS[412]="GBPAUD NZDCHF USDJPY";
      COMBINATIONS[413]="GBPAUD NZDJPY USDCAD";
      COMBINATIONS[414]="GBPAUD NZDJPY USDCHF";
      COMBINATIONS[415]="GBPCAD NZDCHF USDJPY";
      COMBINATIONS[416]="GBPCAD NZDJPY USDCHF";
      COMBINATIONS[417]="GBPCHF NZDCAD USDJPY";
      COMBINATIONS[418]="GBPCHF NZDJPY USDCAD";
      COMBINATIONS[419]="GBPJPY NZDCAD USDCHF";
      COMBINATIONS[420]="GBPJPY NZDCHF USDCAD";
      num_combos=420;
      num_symbols=3;
     }

//---

   if(Generation_Type==twos210)
     {
      COMBINATIONS[1]="AUDCAD CHFJPY";
      COMBINATIONS[2]="AUDCAD EURCHF";
      COMBINATIONS[3]="AUDCAD EURGBP";
      COMBINATIONS[4]="AUDCAD EURJPY";
      COMBINATIONS[5]="AUDCAD EURNZD";
      COMBINATIONS[6]="AUDCAD EURUSD";
      COMBINATIONS[7]="AUDCAD GBPCHF";
      COMBINATIONS[8]="AUDCAD GBPJPY";
      COMBINATIONS[9]="AUDCAD GBPNZD";
      COMBINATIONS[10]="AUDCAD GBPUSD";
      COMBINATIONS[11]="AUDCAD NZDCHF";
      COMBINATIONS[12]="AUDCAD NZDJPY";
      COMBINATIONS[13]="AUDCAD NZDUSD";
      COMBINATIONS[14]="AUDCAD USDCHF";
      COMBINATIONS[15]="AUDCAD USDJPY";
      COMBINATIONS[16]="AUDCHF CADJPY";
      COMBINATIONS[17]="AUDCHF EURCAD";
      COMBINATIONS[18]="AUDCHF EURGBP";
      COMBINATIONS[19]="AUDCHF EURJPY";
      COMBINATIONS[20]="AUDCHF EURNZD";
      COMBINATIONS[21]="AUDCHF EURUSD";
      COMBINATIONS[22]="AUDCHF GBPCAD";
      COMBINATIONS[23]="AUDCHF GBPJPY";
      COMBINATIONS[24]="AUDCHF GBPNZD";
      COMBINATIONS[25]="AUDCHF GBPUSD";
      COMBINATIONS[26]="AUDCHF NZDCAD";
      COMBINATIONS[27]="AUDCHF NZDJPY";
      COMBINATIONS[28]="AUDCHF NZDUSD";
      COMBINATIONS[29]="AUDCHF USDCAD";
      COMBINATIONS[30]="AUDCHF USDJPY";
      COMBINATIONS[31]="AUDJPY CADCHF";
      COMBINATIONS[32]="AUDJPY EURCAD";
      COMBINATIONS[33]="AUDJPY EURCHF";
      COMBINATIONS[34]="AUDJPY EURGBP";
      COMBINATIONS[35]="AUDJPY EURNZD";
      COMBINATIONS[36]="AUDJPY EURUSD";
      COMBINATIONS[37]="AUDJPY GBPCAD";
      COMBINATIONS[38]="AUDJPY GBPCHF";
      COMBINATIONS[39]="AUDJPY GBPNZD";
      COMBINATIONS[40]="AUDJPY GBPUSD";
      COMBINATIONS[41]="AUDJPY NZDCAD";
      COMBINATIONS[42]="AUDJPY NZDCHF";
      COMBINATIONS[43]="AUDJPY NZDUSD";
      COMBINATIONS[44]="AUDJPY USDCAD";
      COMBINATIONS[45]="AUDJPY USDCHF";
      COMBINATIONS[46]="AUDNZD CADCHF";
      COMBINATIONS[47]="AUDNZD CADJPY";
      COMBINATIONS[48]="AUDNZD CHFJPY";
      COMBINATIONS[49]="AUDNZD EURCAD";
      COMBINATIONS[50]="AUDNZD EURCHF";
      COMBINATIONS[51]="AUDNZD EURGBP";
      COMBINATIONS[52]="AUDNZD EURJPY";
      COMBINATIONS[53]="AUDNZD EURUSD";
      COMBINATIONS[54]="AUDNZD GBPCAD";
      COMBINATIONS[55]="AUDNZD GBPCHF";
      COMBINATIONS[56]="AUDNZD GBPJPY";
      COMBINATIONS[57]="AUDNZD GBPUSD";
      COMBINATIONS[58]="AUDNZD USDCAD";
      COMBINATIONS[59]="AUDNZD USDCHF";
      COMBINATIONS[60]="AUDNZD USDJPY";
      COMBINATIONS[61]="AUDUSD CADCHF";
      COMBINATIONS[62]="AUDUSD CADJPY";
      COMBINATIONS[63]="AUDUSD CHFJPY";
      COMBINATIONS[64]="AUDUSD EURCAD";
      COMBINATIONS[65]="AUDUSD EURCHF";
      COMBINATIONS[66]="AUDUSD EURGBP";
      COMBINATIONS[67]="AUDUSD EURJPY";
      COMBINATIONS[68]="AUDUSD EURNZD";
      COMBINATIONS[69]="AUDUSD GBPCAD";
      COMBINATIONS[70]="AUDUSD GBPCHF";
      COMBINATIONS[71]="AUDUSD GBPJPY";
      COMBINATIONS[72]="AUDUSD GBPNZD";
      COMBINATIONS[73]="AUDUSD NZDCAD";
      COMBINATIONS[74]="AUDUSD NZDCHF";
      COMBINATIONS[75]="AUDUSD NZDJPY";
      COMBINATIONS[76]="CADCHF EURAUD";
      COMBINATIONS[77]="CADCHF EURGBP";
      COMBINATIONS[78]="CADCHF EURJPY";
      COMBINATIONS[79]="CADCHF EURNZD";
      COMBINATIONS[80]="CADCHF EURUSD";
      COMBINATIONS[81]="CADCHF GBPAUD";
      COMBINATIONS[82]="CADCHF GBPJPY";
      COMBINATIONS[83]="CADCHF GBPNZD";
      COMBINATIONS[84]="CADCHF GBPUSD";
      COMBINATIONS[85]="CADCHF NZDJPY";
      COMBINATIONS[86]="CADCHF NZDUSD";
      COMBINATIONS[87]="CADCHF USDJPY";
      COMBINATIONS[88]="CADJPY EURAUD";
      COMBINATIONS[89]="CADJPY EURCHF";
      COMBINATIONS[90]="CADJPY EURGBP";
      COMBINATIONS[91]="CADJPY EURNZD";
      COMBINATIONS[92]="CADJPY EURUSD";
      COMBINATIONS[93]="CADJPY GBPAUD";
      COMBINATIONS[94]="CADJPY GBPCHF";
      COMBINATIONS[95]="CADJPY GBPNZD";
      COMBINATIONS[96]="CADJPY GBPUSD";
      COMBINATIONS[97]="CADJPY NZDCHF";
      COMBINATIONS[98]="CADJPY NZDUSD";
      COMBINATIONS[99]="CADJPY USDCHF";
      COMBINATIONS[100]="CHFJPY EURAUD";
      COMBINATIONS[101]="CHFJPY EURCAD";
      COMBINATIONS[102]="CHFJPY EURGBP";
      COMBINATIONS[103]="CHFJPY EURNZD";
      COMBINATIONS[104]="CHFJPY EURUSD";
      COMBINATIONS[105]="CHFJPY GBPAUD";
      COMBINATIONS[106]="CHFJPY GBPCAD";
      COMBINATIONS[107]="CHFJPY GBPNZD";
      COMBINATIONS[108]="CHFJPY GBPUSD";
      COMBINATIONS[109]="CHFJPY NZDCAD";
      COMBINATIONS[110]="CHFJPY NZDUSD";
      COMBINATIONS[111]="CHFJPY USDCAD";
      COMBINATIONS[112]="EURAUD GBPCAD";
      COMBINATIONS[113]="EURAUD GBPCHF";
      COMBINATIONS[114]="EURAUD GBPJPY";
      COMBINATIONS[115]="EURAUD GBPNZD";
      COMBINATIONS[116]="EURAUD GBPUSD";
      COMBINATIONS[117]="EURAUD NZDCAD";
      COMBINATIONS[118]="EURAUD NZDCHF";
      COMBINATIONS[119]="EURAUD NZDJPY";
      COMBINATIONS[120]="EURAUD NZDUSD";
      COMBINATIONS[121]="EURAUD USDCAD";
      COMBINATIONS[122]="EURAUD USDCHF";
      COMBINATIONS[123]="EURAUD USDJPY";
      COMBINATIONS[124]="EURCAD GBPAUD";
      COMBINATIONS[125]="EURCAD GBPCHF";
      COMBINATIONS[126]="EURCAD GBPJPY";
      COMBINATIONS[127]="EURCAD GBPNZD";
      COMBINATIONS[128]="EURCAD GBPUSD";
      COMBINATIONS[129]="EURCAD NZDCHF";
      COMBINATIONS[130]="EURCAD NZDJPY";
      COMBINATIONS[131]="EURCAD NZDUSD";
      COMBINATIONS[132]="EURCAD USDCHF";
      COMBINATIONS[133]="EURCAD USDJPY";
      COMBINATIONS[134]="EURCHF GBPAUD";
      COMBINATIONS[135]="EURCHF GBPCAD";
      COMBINATIONS[136]="EURCHF GBPJPY";
      COMBINATIONS[137]="EURCHF GBPNZD";
      COMBINATIONS[138]="EURCHF GBPUSD";
      COMBINATIONS[139]="EURCHF NZDCAD";
      COMBINATIONS[140]="EURCHF NZDJPY";
      COMBINATIONS[141]="EURCHF NZDUSD";
      COMBINATIONS[142]="EURCHF USDCAD";
      COMBINATIONS[143]="EURCHF USDJPY";
      COMBINATIONS[144]="EURGBP NZDCAD";
      COMBINATIONS[145]="EURGBP NZDCHF";
      COMBINATIONS[146]="EURGBP NZDJPY";
      COMBINATIONS[147]="EURGBP NZDUSD";
      COMBINATIONS[148]="EURGBP USDCAD";
      COMBINATIONS[149]="EURGBP USDCHF";
      COMBINATIONS[150]="EURGBP USDJPY";
      COMBINATIONS[151]="EURJPY GBPAUD";
      COMBINATIONS[152]="EURJPY GBPCAD";
      COMBINATIONS[153]="EURJPY GBPCHF";
      COMBINATIONS[154]="EURJPY GBPNZD";
      COMBINATIONS[155]="EURJPY GBPUSD";
      COMBINATIONS[156]="EURJPY NZDCAD";
      COMBINATIONS[157]="EURJPY NZDCHF";
      COMBINATIONS[158]="EURJPY NZDUSD";
      COMBINATIONS[159]="EURJPY USDCAD";
      COMBINATIONS[160]="EURJPY USDCHF";
      COMBINATIONS[161]="EURNZD GBPAUD";
      COMBINATIONS[162]="EURNZD GBPCAD";
      COMBINATIONS[163]="EURNZD GBPCHF";
      COMBINATIONS[164]="EURNZD GBPJPY";
      COMBINATIONS[165]="EURNZD GBPUSD";
      COMBINATIONS[166]="EURNZD USDCAD";
      COMBINATIONS[167]="EURNZD USDCHF";
      COMBINATIONS[168]="EURNZD USDJPY";
      COMBINATIONS[169]="EURUSD GBPAUD";
      COMBINATIONS[170]="EURUSD GBPCAD";
      COMBINATIONS[171]="EURUSD GBPCHF";
      COMBINATIONS[172]="EURUSD GBPJPY";
      COMBINATIONS[173]="EURUSD GBPNZD";
      COMBINATIONS[174]="EURUSD NZDCAD";
      COMBINATIONS[175]="EURUSD NZDCHF";
      COMBINATIONS[176]="EURUSD NZDJPY";
      COMBINATIONS[177]="GBPAUD NZDCAD";
      COMBINATIONS[178]="GBPAUD NZDCHF";
      COMBINATIONS[179]="GBPAUD NZDJPY";
      COMBINATIONS[180]="GBPAUD NZDUSD";
      COMBINATIONS[181]="GBPAUD USDCAD";
      COMBINATIONS[182]="GBPAUD USDCHF";
      COMBINATIONS[183]="GBPAUD USDJPY";
      COMBINATIONS[184]="GBPCAD NZDCHF";
      COMBINATIONS[185]="GBPCAD NZDJPY";
      COMBINATIONS[186]="GBPCAD NZDUSD";
      COMBINATIONS[187]="GBPCAD USDCHF";
      COMBINATIONS[188]="GBPCAD USDJPY";
      COMBINATIONS[189]="GBPCHF NZDCAD";
      COMBINATIONS[190]="GBPCHF NZDJPY";
      COMBINATIONS[191]="GBPCHF NZDUSD";
      COMBINATIONS[192]="GBPCHF USDCAD";
      COMBINATIONS[193]="GBPCHF USDJPY";
      COMBINATIONS[194]="GBPJPY NZDCAD";
      COMBINATIONS[195]="GBPJPY NZDCHF";
      COMBINATIONS[196]="GBPJPY NZDUSD";
      COMBINATIONS[197]="GBPJPY USDCAD";
      COMBINATIONS[198]="GBPJPY USDCHF";
      COMBINATIONS[199]="GBPNZD USDCAD";
      COMBINATIONS[200]="GBPNZD USDCHF";
      COMBINATIONS[201]="GBPNZD USDJPY";
      COMBINATIONS[202]="GBPUSD NZDCAD";
      COMBINATIONS[203]="GBPUSD NZDCHF";
      COMBINATIONS[204]="GBPUSD NZDJPY";
      COMBINATIONS[205]="NZDCAD USDCHF";
      COMBINATIONS[206]="NZDCAD USDJPY";
      COMBINATIONS[207]="NZDCHF USDCAD";
      COMBINATIONS[208]="NZDCHF USDJPY";
      COMBINATIONS[209]="NZDJPY USDCAD";
      COMBINATIONS[210]="NZDJPY USDCHF";
      num_combos=210;
      num_symbols=2;
     }

//---

   if(Generation_Type==indices)
     {
      COMBINATIONS[01]="AUDCAD=+1 AUDCHF=+1 AUDJPY=+1 AUDNZD=+1 AUDUSD=+1 EURAUD=-1 GBPAUD=-1";
      COMBINATIONS[02]="NZDCAD=+1 NZDCHF=+1 NZDJPY=+1 AUDNZD=-1 NZDUSD=+1 EURNZD=-1 GBPNZD=-1";
      COMBINATIONS[03]="GBPCAD=+1 GBPCHF=+1 GBPJPY=+1 EURGBP=-1 GBPUSD=+1 GBPAUD=+1 GBPNZD=+1";
      COMBINATIONS[04]="EURCAD=+1 EURCHF=+1 EURJPY=+1 EURNZD=+1 EURUSD=+1 EURAUD=+1 EURGBP=+1";
      COMBINATIONS[05]="USDCAD=+1 USDCHF=+1 USDJPY=+1 NZDUSD=-1 AUDUSD=-1 EURUSD=-1 GBPUSD=-1";
      COMBINATIONS[06]="AUDCAD=-1 CADCHF=+1 CADJPY=+1 NZDCAD=-1 USDCAD=-1 EURCAD=-1 GBPCAD=-1";
      COMBINATIONS[07]="AUDCHF=-1 CADCHF=-1 CHFJPY=+1 NZDCHF=-1 USDCHF=-1 EURCHF=-1 GBPCHF=+1";
      COMBINATIONS[08]="AUDJPY=-1 CADJPY=-1 CHFJPY=-1 NZDJPY=-1 USDJPY=-1 EURJPY=-1 GBPJPY=-1";
      num_combos=8;
      num_symbols=7;
     }

//---

   num_first=0;
   num_total=num_combos+1;
   num_model=num_combos+2;
   num_main=num_combos+3;
   num_fast=num_combos+4;
   num_slow=num_combos+5;
   num_upper=num_combos+6;
   num_lower=num_combos+7;
   num_zscore=num_combos+8;
   num_macd=num_combos+9;
   dim_size=num_combos+10;

   if(num_combos==0)
     {
      Alert("Zero number of portfolio combinations selected!");
      error=true;
      return;
     }

   if(dim_size>MAX_LINES)
     {
      Alert("Maximum buffers number exceeded!");
      error=true;
      return;
     }

  }
//+------------------------------------------------------------------+

Comments

Markdown supported. Formatting help

Markdown Formatting Guide

Element Markdown Syntax
Heading # H1
## H2
### H3
Bold **bold text**
Italic *italicized text*
Link [title](https://www.example.com)
Image ![alt text](image.jpg)
Code `code`
Code Block ```
code block
```
Quote > blockquote
Unordered List - Item 1
- Item 2
Ordered List 1. First item
2. Second item
Horizontal Rule ---