Kelly Lot Help Please - page 3

 

I would assume the high lighted section is what have been trying to find.

2011.12.16 15:20:37 2008.01.07 00:00 Kelly Experiment GBPUSD,Daily: Alert: Error opening SELL order : invalid function parameter value
2011.12.16 15:20:37 2008.01.07 00:00 Kelly Experiment GBPUSD,Daily: GBPUSD 1 0 1.9737 20 1.9772 1.9617 12332151
2011.12.16 15:20:37 2008.01.07 00:00 Kelly Experiment GBPUSD,Daily: OrderSend error 4051
2011.12.16 15:20:37 2008.01.07 00:00 Kelly Experiment GBPUSD,Daily: invalid lots amount for OrderSend function
2011.12.16 15:20:34 2008.01.04 00:00 Kelly Experiment GBPUSD,Daily: Alert: Error opening SELL order : invalid function parameter value
2011.12.16 15:20:34 2008.01.04 00:00 Kelly Experiment GBPUSD,Daily: GBPUSD 1 0 1.9724 20 1.9759 1.9604 12332151
2011.12.16 15:20:34 2008.01.04 00:00 Kelly Experiment GBPUSD,Daily: OrderSend error 4051
2011.12.16 15:20:34 2008.01.04 00:00 Kelly Experiment GBPUSD,Daily: invalid lots amount for OrderSend function
2011.12.16 15:20:32 2008.01.03 00:40 Kelly Experiment GBPUSD,Daily: Alert: Error opening BUY order : invalid function parameter value
2011.12.16 15:20:32 2008.01.03 00:40 stdlib GBPUSD,Daily: loaded successfully
2011.12.16 15:20:32 2008.01.03 00:40 Kelly Experiment GBPUSD,Daily: GBPUSD 1 0 1.9829 20 1.9794 1.9949 12332151
2011.12.16 15:20:32 2008.01.03 00:40 Kelly Experiment GBPUSD,Daily: OrderSend error 4051
2011.12.16 15:20:32 2008.01.03 00:40 Kelly Experiment GBPUSD,Daily: invalid lots amount for OrderSend function
2011.12.16 15:20:32 2008.01.03 00:20 Kelly Experiment GBPUSD,Daily: close #1 sell 0.01 GBPUSD at 1.98660 sl: 1.99010 tp: 1.97460 at price 1.98318
2011.12.16 15:20:30 2008.01.02 08:00 Kelly Experiment GBPUSD,Daily: GBPUSD 1 0.01 1.9866 20 1.9901 1.9746 12332151
2011.12.16 15:20:30 2008.01.02 08:00 Kelly Experiment GBPUSD,Daily: 0
2011.12.16 15:20:30 2008.01.02 08:00 Kelly Experiment GBPUSD,Daily: Risk by Optimal f : 0.00 lot (SL : 100pips, Fractional)
2011.12.16 15:20:30 2008.01.02 08:00 Kelly Experiment GBPUSD,Daily: Fractional Kelly (0.25) : 0.00%
2011.12.16 15:20:30 2008.01.02 08:00 Kelly Experiment GBPUSD,Daily: Optimal f (Kelly) : 0.00%
2011.12.16 15:20:30 2008.01.02 08:00 Kelly Experiment GBPUSD,Daily: Profit / Loss Ratio : 0.00
2011.12.16 15:20:30 2008.01.02 08:00 Kelly Experiment GBPUSD,Daily: Average Loss : 0.00 USD
2011.12.16 15:20:30 2008.01.02 08:00 Kelly Experiment GBPUSD,Daily: Average Win : 0.00 USD
2011.12.16 15:20:30 2008.01.02 08:00 Kelly Experiment GBPUSD,Daily: Trades : 0 (Total) / 0 (buy) / 0 (sell)
2011.12.16 15:20:30 2008.01.02 08:00 Kelly Experiment GBPUSD,Daily: open #1 sell 0.01 GBPUSD at 1.98660 sl: 1.99010 tp: 1.97460 ok
2011.12.16 15:20:30 2008.01.02 08:00 Kelly Experiment GBPUSD,Daily: 0
2011.12.16 15:20:30 2008.01.02 08:00 Kelly Experiment GBPUSD,Daily: Risk by Optimal f : 0.00 lot (SL : 100pips, Fractional)
2011.12.16 15:20:30 2008.01.02 08:00 Kelly Experiment GBPUSD,Daily: Fractional Kelly (0.25) : 0.00%
2011.12.16 15:20:30 2008.01.02 08:00 Kelly Experiment GBPUSD,Daily: Optimal f (Kelly) : 0.00%
2011.12.16 15:20:30 2008.01.02 08:00 Kelly Experiment GBPUSD,Daily: Profit / Loss Ratio : 0.00
2011.12.16 15:20:30 2008.01.02 08:00 Kelly Experiment GBPUSD,Daily: Average Loss : 0.00 USD
2011.12.16 15:20:30 2008.01.02 08:00 Kelly Experiment GBPUSD,Daily: Average Win : 0.00 USD
2011.12.16 15:20:30 2008.01.02 08:00 Kelly Experiment GBPUSD,Daily: Trades : 0 (Total) / 0 (buy) / 0 (sell)

   double Kellylot = 0.0;
   if(StopLoss_for_Kellylot>0.001)
   Kellylot=(AccountBalance() * Optimal_f*Fractional_Kelly) / ( MarketInfo(Symbol(),MODE_TICKVALUE) * StopLoss_for_Kellylot * DQADJ );
   Print( "Risk by Optimal f : "+DoubleToStr(Kellylot,Ldig) +" lot (SL : "+StopLoss_for_Kellylot+"pips"+Fractional+")");
//--- check min, max and step
   Kellylot=NormalizeDouble(Kellylot/lot_step,0)*lot_step;
   Print (NormalizeDouble(Kellylot/lot_step,0)*lot_step);
   if(Kellylot<lot_min) Kellylot=lot_min;
   if(Kellylot>lot_max) Kellylot=lot_max;
//---
   return(Kellylot);
      }
     }
 
kiwi06:

Attached is a mock up EA that has the original EA in it just to see was the out puts would be.

its not optimised or very good for that matter.

if you run a demo you will see the Risk by Optimal F starting at 0.00 in moving to -0.19 or something then up to a positive GBPUSD Daily was the pair and for every win it moves up depending on the size of the win and vice versa for the loss.

I have been trying to use the Risk by Optimal F as the lot size for the EA so if there is a - 0.19 that needs to = the minimum lot size for the broker.

I hope that helps out a little

For the Pivot.mq4 file the problem area is shown below (but fixed)

void CheckForOpen(string symbol){
   int    res;
   double h = iHigh(NULL,0,1);
   double l = iLow (NULL,0,1);
  
   double stopLoss = (h-l)/Point;   // stopLoss measured in Points from the current level
   if( stopLoss < 1.5 * MarketInfo(symbol,MODE_STOPLEVEL) ) // factor of 1.5 because being close to the stops level causes occasional failures
       stopLoss = 1.5 * MarketInfo(symbol,MODE_STOPLEVEL);
     
   double SL,TP;
   //---- sell conditions
   if(sellsig && ttime!=Time[0]){
      double bid = NormalizeDouble(Bid, Digits);
      SL =         NormalizeDouble(Bid + stopLoss * dXPoint * Point, Digits);
      TP =         NormalizeDouble(Bid - TakeProfit*dXPoint * Point, Digits);
      res=OrderSend(symbol,OP_SELL,Lots,bid,slippage,SL,TP,"Pivot Sell",MAGICNUM,0,Red);
        if( res<0 ){
          Print("Error opening SELL order : ",ErrorDescription(GetLastError()));
          Print("Bid=" + DoubleToStr(bid,Digits) + " : SL=" + DoubleToStr(SL,Digits) + ": TP=" + DoubleToStr(TP,Digits));
      }
      
      ttime=Time[0];
      return;
   }
   
   //---- buy conditions
   if(buysig && ttime!=Time[0])  {
      double ask = NormalizeDouble(Ask, Digits);
      SL =         NormalizeDouble(Ask - stopLoss * dXPoint * Point, Digits);
      TP =         NormalizeDouble(Ask + TakeProfit*dXPoint * Point, Digits);

      res=OrderSend(symbol,OP_BUY,Lots,ask,slippage,SL,TP,"Pivot Buy",MAGICNUM,0,Blue);
        if( res<0 ){
          Print("Error opening BUY order : ",ErrorDescription(GetLastError()));
          Print("Ask=" + DoubleToStr(ask,Digits) + " : SL=" + DoubleToStr(SL,Digits) + ": TP=" + DoubleToStr(TP,Digits));
      }
      
      ttime=Time[0];
      return;
   }
}

It was giving INVALID_STOPS on both buy and sell orders so I commented out the buy orders, then made the TP=0, then the SL=0, at which point the errors stopped. Hence the SL was the problem.

Without a debugger you have to narrow down the problem area by simplifying the code or adding tests to narrow down the problem area. Sometimes I literally add Print("Got Here") and move that through the code until I find where it gets stuck.

 
kiwi06:

I would assume the high lighted section is what have been trying to find.

Whoever wrote this code (below) ought to be shot ...

   if(Fractional_Kelly < 0.9999) 
   string Fractional = ""; if(Fractional_Kelly < 0.9999) Fractional = ", Fractional";
   Print("Fractional Kelly ("+DS2(Fractional_Kelly)+") : "+DS2(Optimal_f*Fractional_Kelly*100) +"%");

The original Kellylot() function was badly indented throughout such that it took longer than necessary to notice that the lotsize trap at the end was being bypassed.

Corrected below.

//+------------------------------------------------------------------+
//| Calculate Kelly Lot Size                                         |
//+------------------------------------------------------------------+
   double Kellylot(){ 
      double lot_min =MarketInfo(Symbol(),MODE_MINLOT);
      double lot_max =MarketInfo(Symbol(),MODE_MAXLOT);
      
      double BUY_TRADES = Trades(0);
      double SELL_TRADES = Trades(1);
      double TOTAL_TRADES = BUY_TRADES + SELL_TRADES;
      
      DIGITS = MarketInfo(Symbol(),MODE_DIGITS);
      DQADJ = DQ_ADJUST [ DIGITS ];

      Ldig = 2;
      if(MarketInfo(Symbol(),MODE_MINLOT) > 0.07) Ldig = 1;
      
      if(MarketInfo(Symbol(),MODE_MINLOT) > 0.7) Ldig = 0;
      
      if(OrdersHistoryTotal() < 1 || TOTAL_TRADES < 0.9){
      
         // Statistics --------------------------------------
         double BUY_WINS  =  Wins(0);
         double BUY_LOSSES = BUY_TRADES -  BUY_WINS; 
         double SELL_WINS =  Wins(1);
         double SELL_LOSSES = SELL_TRADES - SELL_WINS; 
         double TOTAL_WINS =  BUY_WINS + SELL_WINS;
         double TOTAL_LOSSES = TOTAL_TRADES - TOTAL_WINS; 

         // Winning Average
         double WinAv_Total = 0.0;
         if( TOTAL_TRADES > 0.001 )
            WinAv_Total = TOTAL_WINS / TOTAL_TRADES;
         Print("Trades : " + DS0(TOTAL_TRADES) +" (Total) / "+DS0(BUY_TRADES) +" (buy) / "+DS0(SELL_TRADES) +" (sell)");

         // Average P/L
         double Buy_Profit =   Profit(0);
         double Sell_Profit =  Profit(1);
         double Total_Profit = Buy_Profit + Sell_Profit;
         double Buy_Loss =  Loss(0);
         double Sell_Loss = Loss(1);
         double Total_Loss = Buy_Loss + Sell_Loss;

         double Av_Profit_Total = 0.0;
         if( TOTAL_WINS > 0.001 )
            Av_Profit_Total = Total_Profit / TOTAL_WINS;

         double Av_Loss_Total = 0.0;
         if( TOTAL_LOSSES > 0.001 )
            Av_Loss_Total = Total_Loss / TOTAL_LOSSES;

         double PL_RATIO_Total = 0.0;
         if( Av_Loss_Total > 0.001 )
            PL_RATIO_Total = Av_Profit_Total / Av_Loss_Total;

         Print("Average Win : "+DS2(Av_Profit_Total) +" "+AccountCurrency());
         Print("Average Loss : "+DS2(Av_Loss_Total) +" "+AccountCurrency());
         Print("Profit / Loss Ratio : "+DS2(PL_RATIO_Total));

         // Optimal f (Kelly)   
         double Optimal_f = 0.0;
         if(PL_RATIO_Total > 0.001)
            Optimal_f = ( (PL_RATIO_Total + 1) * WinAv_Total - 1 ) / PL_RATIO_Total;  
         Print("Optimal f (Kelly) : "+DS2(Optimal_f * 100) +"%");
      
         string Fractional = "";       // NOTE: compare this to the previous version which was AAAARRH!!!!!!!         
         if( Fractional_Kelly < 0.9999 )
             Fractional = ", Fractional";
            
         Print("Fractional Kelly ("+DS2(Fractional_Kelly)+") : "+DS2(Optimal_f*Fractional_Kelly*100) +"%");

          //--- basic kelly formula
         double kellyLOT = 0.0;
         if( StopLoss_for_Kellylot>0.001 )
            kellyLOT=(AccountBalance() * Optimal_f*Fractional_Kelly) / ( MarketInfo(Symbol(),MODE_TICKVALUE) * StopLoss_for_Kellylot * DQADJ );

         Print( "Risk by Optimal f : "+DoubleToStr(kellyLOT,Ldig) +" lot (SL : "+StopLoss_for_Kellylot+"pips"+Fractional+")");
      }
      
      //--- check min and max Lot sizes AND trap stupid values
      if( kellyLOT < lot_min )
          kellyLOT = lot_min;
         
      if( kellyLOT > lot_max )
          kellyLOT = lot_max;
          
      return(kellyLOT);
}
 

Hi dabbler

Some days I think I am getting the hang of this coding lark. Then I come onto a forum like this and get a massive reality check I gues its just not in my DNA.

In both instances the code is massively different and very clean and tidy I now understand what you mean be normalizing under the OrderSend().

Now what do I need to do in order to get the kellyLot into the OrderSend().

And I know I need to go through the mql book another couple of times.


Kind Regards


Kiwi

 
kiwi06:

Now what do I need to do in order to get the kellyLot into the OrderSend().



Try this ...

// these next three lines should go at the top of the file
extern string _= "stopLoss and takeProfit are in POINTS";
extern double  stopLoss =   350;  
extern double  takeProfit = 1200; 

void CheckForOpen(string symbol) {
   int    res;
   
   double lotSize= NormalizeDouble(Kellylot(),2);
   if( lotSize < 0.01 )                 // this test is redundant now that the lotsize is trapped correctly in Kellylot()
      Print("Error in lotsize=" + DoubleToStr(lotSize,2));
   
   // this is not a very efficient location for these tests. They should really be done in the init() function
   if( stopLoss < 1.5 * MarketInfo(symbol,MODE_STOPLEVEL) ) // factor of 1.5 because being close to the stops level causes occasional failures
       stopLoss = 1.5 * MarketInfo(symbol,MODE_STOPLEVEL);

   if( takeProfit < 1.5 * MarketInfo(symbol,MODE_STOPLEVEL) ) // factor of 1.5 because being close to the stops level causes occasional failures
       takeProfit = 1.5 * MarketInfo(symbol,MODE_STOPLEVEL);

   double SL,TP;
   //---- sell conditions
   if(sellsig && ttime!=Time[0]){
      double bid = NormalizeDouble(Bid, Digits);
      SL =         NormalizeDouble(Bid + stopLoss * Point, Digits);
      TP =         NormalizeDouble(Bid - takeProfit*Point, Digits);
      res=OrderSend(symbol,OP_SELL,lotSize,bid,slippage,SL,TP,"t3",SpecificMagic,0,Red);
      if( res<0 ){
          Print("Error opening SELL order : ",ErrorDescription(GetLastError()));
          Print("Bid=" + DoubleToStr(bid,Digits) + " : SL=" + DoubleToStr(SL,Digits) + ": TP=" + DoubleToStr(TP,Digits));
      }
      
      ttime=Time[0];
      return;
   }

   //---- buy conditions
   if(buysig && ttime!=Time[0])  {
      double ask = NormalizeDouble(Ask, Digits);
      SL =         NormalizeDouble(Ask - stopLoss  * Point, Digits);
      TP =         NormalizeDouble(Ask + takeProfit* Point, Digits);

      res=OrderSend(symbol,OP_BUY,lotSize,ask,slippage,SL,TP,"t3",SpecificMagic,0,Blue);
      if( res<0 ){
          Print("Error opening BUY order : ",ErrorDescription(GetLastError()));
          Print("Ask=" + DoubleToStr(ask,Digits) + " : SL=" + DoubleToStr(SL,Digits) + ": TP=" + DoubleToStr(TP,Digits));
      }
      
      ttime=Time[0];
      return;
   }
}    

The code now runs without errors, but i doubt it is doing what you want. It seems to be closing orders almost as soon as they are opened and is remarkably unprofitable.


Time to dive in there and really make the code your own. And note that the MLQ4 coding examples are not in any style of C programming that I have seen. (Aarrrgh!!!)

 

Hi dabbler

Thanks for taking the time to show be the error of my ways so to speak. The only thing that is not working is the lot size is not changing for some reason there is only 0.01 which the below is picking up the error I think

   double lotSize= NormalizeDouble(Kellylot(),2);
   if( lotSize < 0.01 )                 // this test is redundant now that the lotsize is trapped correctly in Kellylot()
      Print("Error in lotsize=" + DoubleToStr(lotSize,2));

where the Error in lotsize=0.01 happens is where is lot size should increase. well it does on the comments on screen.

2011.12.17 13:23:12 2009.05.07 02:20 Pivot GBPUSD,Daily: Error in lotsize=0.01
2011.12.17 13:23:12 2009.05.07 02:00 Pivot GBPUSD,Daily: Error in lotsize=0.01
2011.12.17 13:23:12 2009.05.07 01:40 Pivot GBPUSD,Daily: Error in lotsize=0.01
2011.12.17 13:23:12 2009.05.07 01:20 Pivot GBPUSD,Daily: Error in lotsize=0.01
2011.12.17 13:23:12 2009.05.07 01:00 Pivot GBPUSD,Daily: Error in lotsize=0.01
2011.12.17 13:23:12 2009.05.07 01:00 Tester: stop loss #112 at 1.51082 (1.50980 / 1.51051)
2011.12.17 13:23:12 2009.05.07 00:40 Pivot GBPUSD,Daily: modify #112 buy 0.01 GBPUSD at 1.51255 sl: 1.51082 tp: 1.52455 ok
2011.12.17 13:23:12 2009.05.07 00:20 Pivot GBPUSD,Daily: modify #112 buy 0.01 GBPUSD at 1.51255 sl: 1.51031 tp: 1.52455 ok
2011.12.17 13:23:12 2009.05.07 00:00 Pivot GBPUSD,Daily: open #112 buy 0.01 GBPUSD at 1.51255 sl: 1.50905 tp: 1.52455 ok
2011.12.17 13:23:12 2009.05.07 00:00 Pivot GBPUSD,Daily: Error in lotsize=0.01

 
kiwi06:

where the Error in lotsize=0.01 happens is where is lot size should increase. well it does on the comments on screen.

2011.12.17 13:23:12 2009.05.07 02:20 Pivot GBPUSD,Daily: Error in lotsize=0.01
2011.12.17 13:23:12 2009.05.07 02:00 Pivot GBPUSD,Daily: Error in lotsize=0.01
2011.12.17 13:23:12 2009.05.07 01:40 Pivot GBPUSD,Daily: Error in lotsize=0.01
2011.12.17 13:23:12 2009.05.07 01:20 Pivot GBPUSD,Daily: Error in lotsize=0.01
2011.12.17 13:23:12 2009.05.07 01:00 Pivot GBPUSD,Daily: Error in lotsize=0.01
2011.12.17 13:23:12 2009.05.07 01:00 Tester: stop loss #112 at 1.51082 (1.50980 / 1.51051)
2011.12.17 13:23:12 2009.05.07 00:40 Pivot GBPUSD,Daily: modify #112 buy 0.01 GBPUSD at 1.51255 sl: 1.51082 tp: 1.52455 ok
2011.12.17 13:23:12 2009.05.07 00:20 Pivot GBPUSD,Daily: modify #112 buy 0.01 GBPUSD at 1.51255 sl: 1.51031 tp: 1.52455 ok
2011.12.17 13:23:12 2009.05.07 00:00 Pivot GBPUSD,Daily: open #112 buy 0.01 GBPUSD at 1.51255 sl: 1.50905 tp: 1.52455 ok
2011.12.17 13:23:12 2009.05.07 00:00 Pivot GBPUSD,Daily: Error in lotsize=0.01

This is totally stupid. IT'S NOT POSSIBLE! AARRRGH ...

We normaliize to 2 digits, compare to a 2 digit value, and it says the answer is wrong and then prints it correctly. Doubting my own sanity i wrote a little script to test it.

// to show how un-normliased doubles do not work intuitively at all

double array[]={0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09};

int start(){

   int len = ArraySize(array);
   
   string str="Are Doubles internally represented accurately?\n\n";
   for( int n=0; n<len; n++ ){
      double err = 1000000 * ( NormalizeDouble(array[n],2) - array[n] );
      str = str + DoubleToStr(array[n],2) + " error is " + DoubleToStr(err,1);
      if( NormalizeDouble(array[n],2) > array[n] )
         str = str + " normalized val is >";
      if( NormalizeDouble(array[n],2) < array[n] )
         str = str + " normalized val is <";
      
      str = str + "\n";
   }
   
   Comment(str);

   return(0);
}

This produces no errors. Just delete that test; it is causing trouble unnecessarily. (Probably you could test for < 0.009999 and it would also be fine).

The Kellylot() code is never executed more than once because of this bizarre line ...

      if(OrdersHistoryTotal() < 1 || TOTAL_TRADES < 0.9){

Like i said, you need to go through this code and understand what it is doing, or should be doing, in order to fix it.

Reason: