// Описание индикатора FF_FP
// Индикатор рассчитывает размер позиции по методу фиксированной пропорции Райана Джонса.
// Формула фиксированной пропорции:

//         Lot = MinLot * ( Sqrt [ 0.25 + 2 * ( Balance - Delta ) / Delta ] + 0.5 )

// Lot это размер позиции,
// MinLot - минимальный размер лота,
// Sqrt - квадратный корень.
// Например при Delta = 10000,при начальном балансе счета  Balance = 10000 и при MinLot = 0.01 таблица результатов некоторых
// вычислений по этой формуле будет иметь такой вид

//                          Lot    |  Balance
//                          -----------------
//                          0.01   |   10000
//                          0.02   |   20000
//                          0.03   |   40000
//                          0.04   |   70000
//                          0.05   |  110000
//                          0.06   |  160000
//                          0.07   |  220000
//                          0.08   |  290000

// Значение Delta после прибыльной сделки принимает значение Delta_Growth или значение ставки роста, а после убыточной Delta
// присваивает значение Delta_Decrease или значение ставки снижения
// Величины Delta_Growth и Delta_Decrease это вводные параметры в окне настроек индикатора.

// В окне индикатора рисуется гистограмма баланса счета вкупе со скользящей средней баланса счета по экспоненциальному или
// простому усреднению 

// Индикатор помимо прочих параметров рассчитывает Математическое ожидание  или  Mathematical еxpectation.

// Индикатор также рассчитывает оптимальную фракцию F или Optimum fraction  F  ( Ральф Винс )

// Current Drowdown  проседание счета которое равно расстоянию от максимального баланса счета который был достигнут в ходе
// торгов и с учетом пополнения и снятия средств до минимума баланса который находится между максимальным балансом счета и
// текущим значением баланса счета 
// Net Profit today (%) это профит в течении дня, Net Profit this week (%) - за текущую неделю и Net Profit this month (%)
// за текущий месяц
//------------------------------------------------------------------------------------------------------------------ 

#property indicator_separate_window           // индикатор в отдельном окне
#property indicator_buffers 2                 // количество отображаемых линий 
#property indicator_minimum 0                 // минимальные показания индикатора
#property indicator_color1 LightSteelBlue     // цвет гистограммы баланса счета 
#property indicator_color2 LightSlateGray     // цвет скользящей средней баланса счета
#property indicator_levelcolor SlateGray      // цвет уровня 
#property indicator_style1 0                  // стиль отрисовки столбиков гистограммы баланса счета 
#property indicator_width1 1                  // толщина столбиков гистограммы баланса счета ( вбирается при стеле = 0 )
#property indicator_style2 2                  // стиль отрисовки скользящей средней баланса счета 
#property indicator_width2 1                  // толщина скользящей средней баланса счета ( вбирается при стеле = 0 )
#property indicator_levelstyle 0              // стиль отрисовки уровня 
#property indicator_levelwidth 1              // толщина уровня ( вбирается при стеле = 0 )
#property indicator_level1 0                  // значение уровня 


//---- вводные параметры 


    extern double Delta_Growth = 18;          // Значение Delta для ставки роста 
    extern double Delta_Decrease = 20;        // Значение Delta для ставки снижения
    extern bool Get_report = false;           // Показать отчет по торговле => true / Не показывать => false
    extern int MA_period = 8;                 // Период скользящей средней баланса
    extern bool EMA_true_SMA_false = false;   // Метод вычисления скользящей средней баланса  EMA => true / SMA => false
    
//---------------------------------------------------------------------------------


      double T[2000];
      double B[2000];
      double Buffer[];
      double Buffer1[];
      datetime T1[1000000];
      datetime T2[1000000];         
      double SD[1000000];
      double EZ[1000000];           
      int count;         
      int h = 1;  
   
         
//------------

      int init( )
      {
      
       IndicatorBuffers( 2 );
       IndicatorDigits( 2 ); 
       SetIndexStyle( 0, DRAW_HISTOGRAM );
       SetIndexStyle( 1, DRAW_LINE );
       SetIndexBuffer( 0, Buffer );
       SetIndexBuffer( 1, Buffer1 );
       string name = "Balance";
       string Method = "SMA";
      
      
       if( EMA_true_SMA_false == true )
       {
        Method = "EMA";
       }
      
      
       string name1 = "Average Balance  "+Method+" ("+MA_period+")";
       IndicatorShortName( name );
       SetIndexLabel( 0, name );
       SetIndexLabel( 1, name1 );
       return(0);
      }
      
      
//------------------------------

      int deinit( )
      {
       Comment( " " );
       return(0);
      }
      
//---------------------------------------------------------------------------


      int start( )
      {
      
          
      int i = 0;
      int s2;
      int u2;      
      int oht = OrdersHistoryTotal( );
      if( h >= -98 )
      {
      
        while( i < oht )
        {
        
         if( OrderSelect( i, SELECT_BY_POS, MODE_HISTORY ) == true )
         {
         
           int da1 = OrderType( );
           if( da1 <= 1 )
           {
            SD[s2] = OrderSwap( ) + OrderCommission( ) + OrderProfit( );           
            T1[s2] = OrderCloseTime( );
            T2[s2] = OrderCloseTime( );
            s2++;
            count = s2;
           }         
           
                                       
         }
         
        i++;
       }
       
      ArraySort( T1, count, 0, MODE_ASCEND );
      
      i = 0;
      
      //----------------------------------------------------
                  
        while( i <= count )
        { 
        
            int wo = 0;
            while( wo <= count )
            {
            if( T1[i] == T2[wo] )
            {
             EZ[i] = SD[wo];
            }
            wo++;
            }
            wo = 0;
            
         
         i++;
         }    
           
      
       h--;
      }
             
      i = 0;  
      

//-------------------------------------------------   
   
      double balance = AccountBalance( );
   	if( Get_report == true )
      {
      
       double MaxRisk = 0;
       double TotalRisk = 0;
       double loss = 0;
       double profit = 0;
       double nles = 0;
       double nprofi = 0;
       double Dd = 0;
       double sum = 0;
       double sum1 = 0;
       int sum_ticks;
       double fs = 0;
       double Lp;
       double Ll;
       double u;
       int x4;
       double de3 = 0; 
       int o1 = 0;
       int j = 0;
       double mk = 1000000;
       double en = -1000000;
      // double b1 = 0;
      // double b2 = 0;
       int y5 = 0;
       double SU = 0;
       double EJ = 0;
       int ii = 0;
       int yy = 0;
       int xx = 0;
       int re = 0;
       int es = 0;
       int gb = 0;
       int cn = 0;
       int z = 0;
       double short;
       double long;
       int Total_short;
       int Total_long;
       double SOC;
       double NT1;
       double NW2;
       double NM3;
       int NT1_ticks;
       int NW2_ticks;
       int NM3_ticks;
       int xc;
       int w;
       int l;



       while( i < oht )
       {

         if( i <= count )
         {
      
           if( EZ[i] < 0 )
           {
         
            sum = sum + EZ[i];
            o1++;
            y5++;
          
          
             if( mk > sum )
             {
              mk = sum;
              re = y5;
             }
             
    
               if( xx <= y5 )
               {
                xx = y5;
               }
             
             
                 sum1 = 0; 
                 if( j != 0 )
                 {
                  cn++;
                 } 
           
              
         j = 0;
         ii = 0; 
               
       }
      
      
      //----------------------
      
                    
      if( EZ[i] >= 0 )
      {
      
      
                 if( o1 != 0 )
                 {
                  gb++;
                 }
                   
                       
          o1 = 0;
          y5 = 0;
          sum = 0;     
          sum1 = sum1 + EZ[i];
          j++;
          ii++;
       
      
               if( en < sum1 )
               {
                en = sum1;
                es = ii;
               }
               
               
                  if( yy <= ii )
                  {
                   yy = ii;
                  }
        } 
      
        }

      //-----------------------------------------------------------
      
      if( OrderSelect( i, SELECT_BY_POS, MODE_HISTORY ) == true )
      {
      
        double orderopenprice = OrderOpenPrice( );
        double ordercloseprice = OrderClosePrice( );
        double swap = OrderSwap( );
        datetime closetime = OrderCloseTime( );
        int cmd = OrderType( );
        double commission = OrderCommission( );
        double orderprofit = OrderProfit( );
        
      //--------------------------------------------------------------
      
      if( ( cmd != 2 ) && ( cmd != 3 ) && ( cmd != 4 ) && ( cmd != 5 ) )
      {
      
       xc++;
       
           if( cmd == 6 )
           {
           
             if( orderprofit > 0 )
             {
             // b1 = b1 + orderprofit;
             }
             else
             {
             if( orderprofit < 0 )
             {
              w = xc + 1;
              // b2 = b2 + orderprofit;
             }
             }
             
           }
           
      //-------------------------------------------
      
      
      de3 = de3 + swap + orderprofit + commission;
      B[xc] = de3;


      //------------------------------------------
      
      
      if( cmd <= 1 )
      {
      
          if( orderprofit >= 0 )
          {
           l = 1;
          }
          else
          {
          if( orderprofit < 0 )
          {
           l = -1;
          }
          }
          
          
      double tick = MarketInfo( OrderSymbol( ), MODE_TICKSIZE );
      
      if( tick != 0 )
      {
       x4 = l * MathAbs( orderopenprice - ordercloseprice ) / tick;
       sum_ticks = sum_ticks + x4; 
      }
      
      
      SOC = swap + orderprofit + commission;
      
      //----------------------------------------------------
      
      if( closetime >= iTime( NULL, PERIOD_D1, 0 ) )
      {
      
         if( tick != 0 )
         {      
          NT1_ticks = NT1_ticks + x4;
         }
         
       NT1 = NT1 + SOC;
      } 
      
      //-----------------------------------------------------
      
      if( closetime >= iTime( NULL, PERIOD_W1, 0 ) )
      {
      
         if( tick != 0 )
         {      
          NW2_ticks = NW2_ticks + x4;
         }
         
       NW2 = NW2 + SOC;
      }
      
      //----------------------------------------------------
      
      if( closetime >= iTime( NULL, PERIOD_MN1, 0 ) )
      {
      
         if( tick != 0 )
         {      
          NM3_ticks = NM3_ticks + x4;
         }
         
       NM3 = NM3 + SOC;
      }
      
      //----------------------------------------------------
      
      z++;  
      if( SOC < 0 )
      {

             if( B[xc - 1] != 0 )
             {
              TotalRisk = TotalRisk + 100 * SOC / B[xc - 1];
             }
 
 
      //----------------------------------------------------
      
      
               if( Ll > SOC )
               {
               
                  Ll = SOC;
                     if( B[xc - 1] != 0 )
                     {
                      MaxRisk = 100 * Ll / B[xc - 1];
                     }
                     
                }
                
       //-------------------------------------------------   
             
       nles++;
       loss = loss - SOC;
      }
      else
      {
      if( SOC >= 0 )
      {
      
                 if( cmd == 0 )
                 {
                  long++;
                 }
                 else
                 {
                 if( cmd == 1 )
                 {
                  short++;
                 }
                 }
      
      
      //-----------------------------------------
      
      
                 if( Lp < SOC )
                 {
                  Lp = SOC;
                 } 
                 
                 
         nprofi++;
         profit = profit + SOC;
         }
         }
      }
      
      
      //---------------------
      
      
               if( cmd == 0 )
               {
                Total_long++;
               }
               else
               {
               if( cmd == 1 )
               {
                Total_short++;
               } 
               }
               
               
      }
      }
          
      i++;
      }
      
      i = 0;
      
      //------------------------------------------------------------
      
      
      int oi = 0;
      int maxindex = ArrayMaximum( B, xc, 0 ); 
      double max = B[maxindex];
      
      
      while( oi <= xc - maxindex )
      {
      
        static double min = 1000000;
        if( ( min > B[xc - oi] ) && ( xc - oi > w ) ) 
        {
         min = B[xc - oi];
        }
        
      oi++;
      }
      
      
      Dd = max - min;
      if( max != 0 )
      {
       u = 100 * Dd / max;
      } 
      
      
      //----------------------------------------------------------------------
      
      int ie = 0;
      int t = 0;
      int k2 = 0;
      double fgh = 0;
      double css = 0;
      
      
      while( ie <= count )
      {
      
        if( EZ[ie] < 0 )
        {
        
      
         k2 = 0;
         EJ = 0;      
         t++;
         SU = SU + EZ[ie];
      
      
               if( t == xx )
               {
                css = SU;
                t = 0;
                SU = 0;
               }
               
      }
      else
      {
      if( EZ[ie] >= 0 )
      {
      
      
       t = 0;
       SU = 0;      
       k2++;
       EJ = EJ + EZ[ie];
       
      
            if( k2 == yy )
            {
             fgh = EJ;
             k2 = 0;
             EJ = 0;
            }
            
      }
      }
      
      ie++;
      }
      
      //------------------------------------------------------------------------------------

      
               while( i <= xc )
               { 
                Buffer[i] = B[xc - i];      
                i++;
               }
               
               i = 0;
               
               
      //-----------------------------------------------------------------------------------------------
      
      int nb = xc - MA_period - 1;
      int iz;
      
      while( nb >= 0 )
      {
      
      
        if( EMA_true_SMA_false == false )
        {
        
        
         double vol = 0;
         for( iz = nb; iz <= nb + MA_period - 1; iz++ )
         {
          vol = vol + Buffer[iz];
         }
         
         
             if( MA_period != 0 )
             {
              Buffer1[nb] = vol / MA_period;
             }
      }
      else
      {
      if( EMA_true_SMA_false == true )
      {
      
      
          if( nb == xc - MA_period - 1 )
          { 
           Buffer1[nb + 1] = Buffer[nb + 1];
          }
          
          
        Buffer1[nb]=( ( MA_period - 1 ) * Buffer1[nb + 1] + 2 * Buffer[nb] ) / ( MA_period + 1 );
        
      }
      }
      
      
        if( Bars - nb - 1 < MA_period )
        {
         Buffer1[nb] = 0;
         SetIndexEmptyValue( 1, 0.0 );
        }
      
      
       nb--;
       
      }
      
      //-----------------------------------------------------------------------------------
      
      
      int h = 0;
      double TWR = 1;
      double g;
      double f;
      
      while( h < 99 )
      {
      
       f = f + 0.01;
       int o = 0;
      
         while( o <= count )
         {
         
           if( Ll != 0 )
           { 
            double HPR = 1 - f * EZ[o] / Ll;
           }
           
           TWR  = TWR * HPR;
           o++;
         }
         
               double G = MathPow( TWR, MathPow( z, -1 ) );
               if( G < g )
               {
                double F = 100 * f - 1;
                break;
               }
               
      g = G;
      h++;
      TWR = 1;
      }
      
      
      //---------------------------------------------------------------------------------------------------------
      
      
      if( ( Total_long != 0 ) && ( Total_short != 0 ) )
      {
      double pctLong = 100 * long / Total_long;
      double pctShort = 100 * short / Total_short;
      }
      
      //------------------------------------------------
      
      double Gp = profit;
      double Gl = loss;
      double TN = profit - loss;
      if( ( nles != 0 ) && ( nprofi != 0 ) )
      {
      double AverageRisk = TotalRisk / nles;
      double alt = loss / nles;
      double apt = profit / nprofi;
      }
      
      //--------------------------------------------------
      
      double total = z;
      if( ( total != 0 ) && ( cn != 0 ) && ( gb != 0 ) )
      {
      double EP = TN / total;
      double acw = nprofi / ( cn + 0 );
      double acl = nles / ( gb + 0 );
      double won = 100 * nprofi / total;
      double lS = 100 - won;
      }
      
      //--------------------------------------------------
      
      if( ( alt != 0 ) && ( loss != 0 ) )
      {
      double ME = 0.01 * ( 1 + apt / alt ) * won - 1;
      double pf = profit / loss;
      }
      
      //---------------------------------------------------
      
      double nt1pct = 100 * NT1 / ( balance - NT1 );
      double nw2pct = 100 * NW2 / ( balance - NW2 );
      double nm3pct = 100 * NM3 / ( balance - NM3 );
      SetIndexDrawBegin( 0, Bars - xc );
      SetIndexDrawBegin( 1, Bars - xc + MA_period );
      
      //-------------------------------------------------
      
      Comment( " Profit factor   "+DoubleToStr( pf, 2 )+" ", // информ табло
      "\n ", "Profit trades ( % of total )   "+DoubleToStr( nprofi, 0 )+" ("+DoubleToStr( won, 2 )+" %) ",
      "\n ", "Loss trades ( % of total )   "+DoubleToStr( nles, 0 )+" ("+DoubleToStr( lS, 2 )+" %) ",
      "\n ", "Total trades   "+z+" ",
      "\n ", "Short Positions (won %)   "+Total_short+" ("+DoubleToStr( pctShort, 2 )+" %) ",
      "\n ", "Long Positions (won %)   "+Total_long+" ("+DoubleToStr( pctLong, 2 )+" %) ",
      "\n ", "Gross Profit    "+DoubleToStr( Gp, 2 )+" ",
      "\n ", "Gross Loss    "+DoubleToStr( Gl, 2 )+" ",
      "\n ", "Total Net Profit    "+DoubleToStr( TN, 2 )+" ",
      "\n ", "Total Net Profit_Ticks   "+sum_ticks+" ",
      "\n ", "Expected Payoff   "+DoubleToStr( EP, 2 )+" ",
      "\n ", "Mathematical еxpectation   "+DoubleToStr( ME, 2 )+"",
      "\n ", "Optimum fraction  F   "+DoubleToStr( F, 0 )+" % ",
      "\n ", "Current Drowdown   "+DoubleToStr( Dd, 2 )+"  ("+DoubleToStr( u, 2 )+" %)",
      "\n ", "Net Profit today (%) ( ticks )   "+DoubleToStr( NT1, 2 )+"  ("+DoubleToStr( nt1pct, 2 )+" %)  ("+NT1_ticks+")", 
      "\n ", "Net Profit this week (%) ( ticks )   "+DoubleToStr( NW2, 2 )+"  ("+DoubleToStr( nw2pct, 2 )+" %)  ("+NW2_ticks+")",
      "\n ", "Net Profit this month (%) ( ticks )   "+DoubleToStr( NM3, 2 )+"  ("+DoubleToStr( nm3pct, 2 )+" %)  ("+NM3_ticks+")",
      "\n ", "Largest profit trade   "+DoubleToStr( Lp, 2 )+" ",
      "\n ", "Largest loss trade   "+DoubleToStr( Ll, 2 )+" ",
      "\n ", "Average profit trade   "+DoubleToStr( apt, 2 )+" ",
      "\n ", "Average loss trade   "+DoubleToStr( -alt, 2 )+" ",
      "\n ", "Average Risk trade   "+DoubleToStr( -AverageRisk, 4 )+" %",
      "\n ", "Maximal Risk trade   "+DoubleToStr( -MaxRisk, 4 )+" %",
      "\n ", "Average consecutive wins   "+DoubleToStr( acw, 0 )+" ",
      "\n ", "Average consecutive losses   "+DoubleToStr( acl, 0 )+" ",
      "\n ", "Maximum consecutive wins($)    "+yy+" ("+DoubleToStr( fgh, 2 )+") ",
      "\n ", "Maximum consecutive losses($)   "+xx+" ("+DoubleToStr( css, 2 )+") ",
      "\n ", "Maximal consecutive profit (count)   "+DoubleToStr( en, 2 )+"  ("+es+")",
      "\n ", "Maximal consecutive loss  (count)   "+DoubleToStr( mk, 2 )+"  ("+re+")" ); 
     // "\n ", "Deposit   "+DoubleToStr( b1, 2 )+" ",
     // "\n ", "Withdrawal   "+DoubleToStr( b2, 2 )+" " );
      
      }
      else
      {
   	if( Get_report == false )
   	{
   	
      
               double minlot = MarketInfo( Symbol( ), MODE_MINLOT );
		         double Delta;
		         
		         
		         if( EZ[count-1] >= 0 )
		         {
	             Delta = Delta_Growth;
		         }
		         else
		         {
		         if( EZ[count-1] < 0 )
		         {
		          Delta = Delta_Decrease;
		         }
		         }
		            
		         
		double fp = MathSqrt( 0.25 + 2 * ( balance - Delta ) / Delta ) + 0.5;
	   double lot = NormalizeDouble( minlot * MathRound( fp - 0.5 ), 2 );
		string dD = "Delta_Decrease   "+DoubleToStr( Delta_Decrease, 2 )+"";
		string dG = "Delta_Growth     "+DoubleToStr( Delta_Growth, 2 )+"";
		string v = "Lot   "+DoubleToStr( lot, 2 )+" ";
      Comment( " "+v+" ", "\n ", dG, "\n ", dD );
      
      
		}
      }
      
      //---------------------------------------------------------------------  
      
      
      
      
          
      
      return(0);
      }





