Portfolio-Modeller

2 Views
1 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