The Trade Encouragement Factor, TEF, and Money Management, MM()

 

This brief discussion assumes that you have read “Be In-Phase” ((https://championship.mql5.com/2012/en/2008) and “On the Long Way to Be a Successful Trader” (https://www.mql5.com/en/articles/1571.

The gist of "Be In-Phase" is…

1. There is a zero return curve that relates Avg.Win/Avg.Loss ratios to %Win percentages:

AvgWin/AvgLoss = Zero_R = (100% - %Win) / %Win


2. Offset above the zero return curve is a "safety curve" where the ratio is:

AvgWin/AvgLoss = Safe_R = (110% - %Win) / (%Win – 10%) + 1


These two curves create three areas: the relatively safe trading area located above the safety curve, the profitable, but potentially risky trading area located between the curves, and the losing trading area located below the zero return curve.

The object of the Trade Encouragement Factor (TEF) is to assess where a trading strategy is located relative to these curves. To make this assessment, the strategy is tested over a time frame of approximately 20 trades and the %Win returned by Strategy Tester is plugged into the above two equations and the actual ratio AvgWin/AvgLoss = Real_R is calculated. Then…

TEF = (Real_R – Zero_R) / (Safe_R – Zero_R)

For example, a EURUSD_D1 run of 20 consecutive trades of my SAR ea returned the following values:

average win $799, average loss $307, wins = 40%

Real_R = 799 / 307 = 2.6

Zero_R = (100 – 40) / 40 = 1.5

Safe_R = (110 – 40) / (40 – 10) + 1 = 3.33

TEF = (2.6 – 1.5) / (3.33 – 1.5) = 0.6

The TEF can range from a negative value to a value above 1. A value of 1 is said to be the “holy grail” and can justify ordering a larger lot size. A positive value close to 0 is very risky to trade and should be taken with a smaller lot size or not at all. Of course, negative values produce a guaranteed loss.

The second article mentioned above deals with money management and makes the point that lot size is governed by a number of factors, including the percentage of your capital you are willing to risk on any one trade (Risk_percent as an extern parameter). My suggestion is to make this percentage a function of the TEF as in the following code…


void MM(double slpips, double TEF)
{
   double riskcapital = AccountBalance()*TEF*Risk_percent/100;
   double tickvalue = (MarketInfo(Symbol(),MODE_TICKVALUE));

   if(Digits == 5 || Digits == 3){
      tickvalue = tickvalue*10;
   }
      
   if(slpips<=0) slpips=60;  // my arbitrary choice
   
   Lots=riskcapital/(slpips*tickvalue);

   if( Lots < 0.1 )          // is money enough for opening 0.1 lot?
      if( ( AccountFreeMarginCheck( Symbol(), OP_BUY,  0.1 ) < 10. ) || 
          ( AccountFreeMarginCheck( Symbol(), OP_SELL, 0.1 ) < 10. ) || 
          ( GetLastError() == 134 ) )
                  Lots = 0.0; // not enough
      else        Lots = 0.1; // enough; open 0.1
   else           Lots = NormalizeDouble( Lots, 2 ); 

   if( Lots>=0.1 && autolots==false ) Lots=MathMin(Lots, minLots);

   return;  
} 

An interesting challenge would be to determine the current TEF of the EA on the run based on recent trade results.

Until someone tackles this challenge, perhaps you can test your favourite EA and calculate its best and worst TEF?

If you want me to email an Excel spreadsheet that makes the calculations easy, let me know at engcomp@gmail.com

It seems .xls files can't be attached.

PS: a typical commercial EA with 95% success rate has a TEF of 0.012. No matter how much you play with the numbers, a strategy of many small wins at the price of one big loss doesn't get the TEF over 0.08 at best.

 
  1. Interesting thoughts. I've incorporated the TSSF (= Real_R / Safe_R) into my EA by multiplying the final Lots by

    adjFact = MathMin(1,(TSSF-1)/(TSSF.Max-1)); // TSSF.Max = 3.

    Completely unoptimized, the EA had no drawdowns and one small area of 50% profit where TSSF went above 1 and the EA went to trading with the max 5%. So the concept has merit. Once I finish the optimization I'll compare the two approaches and report back.


  2. Lots=riskcapital/(slpips*tickvalue);
    This won't work directly. You're checking for minlot but not adjusting for lotstep
    double LotStep = MarketInfo(Symbol(), MODE_LOTSTEP);
    Lots = MathFloor(Lots/ LotStep)*LotStep);
    
 
It's a nice engineering approach. I rather these types of approaches instead of guessing. Is the big idea here, to have some form of self-adjusting factor which stops the system from trading based on performance of x-number of recent trades?
 
WHRoeder:
  1. Interesting thoughts. I've incorporated the TSSF (= Real_R / Safe_R) into my EA by multiplying the final Lots by

    Completely unoptimized, the EA had no drawdowns and one small area of 50% profit where TSSF went above 1 and the EA went to trading with the max 5%. So the concept has merit. Once I finish the optimization I'll compare the two approaches and report back.


  2. This won't work directly. You're checking for minlot but not adjusting for lotstep


Thanks for the tip on lotstep, I shall change my code accordingly.

Your adjustment (TSSF-1) is fine. Does that come to the same value as TEF? Shall look into it.

Do you actually update the TSSF with the latest trade result, dropping off result #21?

If so, I'd love to see the code for it.

I just replied to ubzen's email (requesting the spreadsheet) as follows...

The Be In-Phase article uses a TSSF (Trade System Safety Factor) to compare the effectiveness of different trading strategies.
This works fine as a comparison but doesn't tell you where the strategy lies on the profit spectrum. That's where TEF comes in.
At this time, I use it to assess the likely profitability of a strategy. Good if TEF gets close to 1, bad if it gets close to 0.

I was surprised how bad commercial EAs rank on the basis of TEF. I would be interested how your system ranks?

Thanks for your interest, Helmut

 

Ok, I ran my system from 06/27/2010---07/05/2010. It generated 19 trades. I hope thats sufficient enough. Thanks for the spread sheet as I suck at math and that helped. The results are as follows:

win% 68
AvgWin 100
AvgLoss 53
Real_R 1.886792453
Zero_R 0.470588235
Safe_R 1.724137931
TEF 1.129755144

 

Looks good on such small sample. You're on to something here. Sorry, as I wouldn't be of much help in developing a Criterion. Nor would I be of much help programming any practical tools with this idea. However, I'm more than happy to volunteer as a lab rat. The next logical step I can think of is how-to program this into the system so that when TEF drops below say 0.5 to stop using certain sub-systems (example trend-systems) if they're the ones generating the loses. Then capitalize on the range bound systems.

 

There's another article you placed on here, it showed optimization based on maximum draw-downs. I'm hoping thats what it's doing because it's otherwise just optimizing based on distance between 2 moving averages, which in that case is of little importance to me. Also I need to read that “On the Long Way to Be a Successful Trade" as my money management is as basic as.

Lots=NormalizeDouble((AccountEquity()*Profit_F),1);
if(Lots<0.1){Lots=0.1;}if(Lots>25.0){Lots=25.0;}

Where Profit factor=1.3 (double Profit_F=0.000013), the results that I showed you in the 5% returns thread was based on  (double Profit_F=0.00004). However when I do go live its gonna become whatever the system profit factor is at that time. Something tells me, I'd be under-betting the system big-time, but, better save than sorry.

 

Thanks for the links,file and concepts.

 
ubzen:

Ok, I ran my system from 06/27/2010---07/05/2010. It generated 19 trades. I hope thats sufficient enough. Thanks for the spread sheet as I suck at math and that helped. The results are as follows:

win% 68
AvgWin 100
AvgLoss 53
Real_R 1.886792453
Zero_R 0.470588235
Safe_R 1.724137931
TEF 1.129755144

Looks good on such small sample. You're on to something here. Sorry, as I wouldn't be of much help in developing a Criterion. Nor would I be of much help programming any practical tools with this idea. However, I'm more than happy to volunteer as a lab rat. The next logical step I can think of is how-to program this into the system so that when TEF drops below say 0.5 to stop using certain sub-systems (example trend-systems) if they're the ones generating the loses. Then capitalize on the range bound systems.

I think your system is a serious contender for the "Hall of Fame" with a TEF of 1.13!

This is 13% above the "Holy Grail". Would you share the details of your system with us, please?

The sample size is correct. You may have picked the best period.

Now go and pick the WORST period. If you still get positive TEF instead of negative, you have hit pay-dirt.

The next stage is to detect good from bad periods while the EA is running and take positions accordingly.

 
engcomp:

I think your system is a serious contender for the "Hall of Fame" with a TEF of 1.13!

This is 13% above the "Holy Grail". Would you share the details of your system with us, please?

The sample size is correct. You may have picked the best period.

Now go and pick the WORST period. If you still get positive TEF instead of negative, you have hit pay-dirt.

The next stage is to detect good from bad periods while the EA is running and take positions accordingly.


1) Thanks, but it's only Theoretical System...(Non-Live Results)

 

2) It's CURVE FITTED, Traders Beware!!... Wouldn't consider Holy-Anything unless Live results after 6 months resembles the backtests. 

 

I don't feel comfortable just giving the codes away. As I don't know what it's worth if anything. Hope you can understand. However I don't mind saying what in it and how it came to being.

 

It's made of these Indicators:  Adx, Band, Cci, Cntr, Gaps, Macd, RSI and Stochastic. Those are the core Indicators meaning whenever I back test from 1999 those are in. I also have Pivot-Points and News Trading. Back-testing News slows down to a craw. The Cntr stands for Counter Trend System. They were all created separately and then Cut and Pasted into my Ubzen System. Therefore I can turn off a sub-system with one of these /*  */.

 

The pivot-points shows a profit factor of about 1.70 for the past 3 years. Before then it sucked. I believe Lazy traders are buying into the Pivot Idea therefore price tend to move around those levels. It's a psychological-pivot IMO, and I've deducted TA as mostly psychological trading.

 

I've been warned about the Dangers of Over-Optimizing (Curve fitting). However, I don't have an alternative that's why I'm using the best approach I've got. My thinking is that ALL these system's are Not gonna Break within the same Time-frame. Yeah, I've got 6 Trend based Indicators A,B,Cc,M,R,S however, I've got other things which I'm hoping would keep the system afloat during those choppy times. Also, the trend followers usually have SL around 30-50 points and TP around 150-300 points and about 3 employ trailing stops. The trend win-rate rarely exceed 39%. However the other stuff have better win-rate like 93% but require bigger SL like 150 with TP of 40 for example. Two of them are mid-range like 50/50 sl/tp I think.

 

My intension at this time is to Re-optimize those subsystems every weekend. If that turns out to be redundant then I may re-optimize every month or so. This is where your TEF might come in handy. I always believed trading is not a one tool fits all, "A trader needs to know what market he's in" i.e trending or sideways and use strategies that best exploits those periods.' IMO.

 

3) I'll go get the worse period and post it here. However, this is a very active system and just off the top of my head, between 1999-today, it'd had a consecutive loss of 10 trades in a row. I don't know if it'll produce TEF over 0.5 in that time-frame but we'll see.

 

I'll keep searching for systems which have Universal Application with Minimum Optimization. I'm a little skeptical of that type of approach. Seems to me, if someone have such a system, it's not based on any Indicator, Oscillator or TA studies. However, allot of people seem to be looking for the magic approach like (Fractal or Wave) which could be applied unto any Instrument on any Time-Frame and still works.

 

IMHO, If a system like that existed, Why would the creator use it on Hourly time frame or 5-Minutes time frames for that matter. He'd just run this system on Minute Charts maybe less, if he can help it and crank up the orders.

 
ubzen:


It's made of these Indicators: Adx, Band, Cci, Cntr, Gaps, Macd, RSI and Stochastic. Those are the core Indicators meaning whenever I back test from 1999 those are in. I also have Pivot-Points and News Trading. Back-testing News slows down to a craw. The Cntr stands for Counter Trend System. They were all created separately and then Cut and Pasted into my Ubzen System. Therefore I can turn off a sub-system with one of these /* */.

No matter what the approach, the question is always "tomorrow up, down or sideways?".

Charts are full of lines. The label of a line is "Support" if it is below the current price, or "Resistance" if it is above.

When the price hits one of these lines, there are two possibilities:

1. it keeps going; or

2. it bounces off.

These events may be immediate or may be delayed by the price creeping along the line for a while.

The search for the "holy grail" is about predicting which of these two events will prevail in the given situation.

 
engcomp:
Your adjustment (TSSF-1) is fine. Does that come to the same value as TEF? Shall look into it.

Do you actually update the TSSF with the latest trade result, dropping off result #21?

If so, I'd love to see the code for it.

I don't know yet how my approach compares to TEF.

Yes I update TSSF dropping off result 21 with two differences.
  1. I adjust the lot size instead of the account balance. This allows me to differentiate lack of margin (stacking a second order on small account) vs low TSSF. If there is sufficient margin, then I want to trade at least minlot to avoid a low TSSF from stopping all trading and essentially shutting the EA down.
  2. Initially I have no historical trades so I want to trade the minimum, but I didn't want to have to trade all 20 before starting to use TSSF. Also if the EA isn't trading much and the Terminal is set to only show one month of history or a small custom period, then there may never be 20 trades in history! So I add some equal wins and losses to make 20 so TSSF starts at 1 and slowly ramps to the actual value. This avoids the case where one win bumps TSSF up and the next trade is a looser with a large lot size. AveW/AveL is then hosed until it gets bumped.
//+------------------------------------------------------------------+
//| Trading System Safey Factor                                      |
//+------------------------------------------------------------------+
void    ComputeTSSF(){
    int     tradesWinning=0,    tradesLoosing=0,    tradesCount=0;
    double  profit=0,           loss=0;
    for(int pos = HistoryTotal() - 1; pos >= 0; pos--) if (
        OrderSelect(pos, SELECT_BY_POS, MODE_HISTORY)   // Only my orders w/
    &&  OrderMagicNumber()  == Magic.Number             // my magic number
    &&  OrderType()         <= OP_SELL  // Avoid cr/bal https://www.mql5.com/en/forum/126192
    &&  OrderSymbol()       == Symbol() ){              // and period and symbol
        if(OrderProfit()>=0){   tradesWinning++;    profit += OrderProfit(); }
        else                {   tradesLoosing++;    loss   -= OrderProfit(); }
        tradesCount++;  if (tradesCount == TSSF.Window) break;
    }
    while (tradesCount < TSSF.Window) {     tradesCount += 2;
        profit += 1;    tradesWinning++;    loss += 1;  tradesLoosing++;    }
    win.fraction    = (1.*tradesWinning)/tradesCount;       // Export to Comment
    if (tradesLoosing == 0){
        TSSF = TSSF.Max;    WLR.actual=99; }    // :)
    else {                                                              double
        averageWin      =     profit/MathMax(1,tradesWinning),
        averageLoss     =       loss/          tradesLoosing;
        WLR.actual      = averageWin/averageLoss;   // Win/Loss Ratio.
        if (win.fraction < 0.11)    TSSF = 0;           // Avoid divide by zero.
        else {                                                          double
            WLRsafe     = (1.1-win.fraction)/(win.fraction-0.1)+1;
            TSSF        = WLR.actual/WLRsafe;               // Export to LotSize
        }   // win.fraction > 0.15
    }   // tradesLoosing != 0
}

//+------------------------------------------------------------------+
//| Lot size computation.                                            |
//+------------------------------------------------------------------+
double  LotSize(double SL_points){
    /* This function computes the lot size for a trade.
     * Explicit inputs are SL relative to bid/ask (E.G. SL=30*points,)
     * Implicit inputs are the MM mode, the MM multiplier, count currently
     * filled orders by all EA's vs this EA and Previous closed orders list.
     * Implicit inputs are all used to reduce available balance the maximum
     * dollar risk allowed. StopLoss determines the maximum dollar risk possible
     * per lot. Lots=maxRisk/maxRiskPerLot
     **************************************************************************/

    /*++++ Compute lot size based on account balance and MM mode*/{
    double  ab  = AccountBalance();
    switch(MMMode_F0M1G2){
    case MMMODE_FIXED:
        at.risk = MMMultplier;
        break;
    case MMMODE_MODERATE:
        // See https://www.mql5.com/en/articles/1526 Fallacies, Part 1: Money
        // Management is Secondary and Not Very Important.
        at.risk = MathSqrt(MMMultplier * ab)/ab;     // % used/trade ~const.
        at.risk = MathSqrt(MMMultplier * ab
                            * MathPow( 1 - at.risk, OrdersTotal()-oo.count ));
        break;
    case MMMODE_GEOMETRICAL:
        at.risk = MMMultplier * ab
                            * MathPow(1 - MMMultplier, OrdersTotal()-oo.count);
        break;
    }
    double  maxLossPerLot   = SL_points/Point
                            * MarketInfo( Symbol(), MODE_TICKVALUE ),
            minLot      = MarketInfo(Symbol(), MODE_MINLOT),
    // IBFX demo/mini       EURUSD TICKVALUE=0.1 MAXLOT=50 LOTSIZE=10,000
    // In tester I had a sale: open=1.35883 close=1.35736 (0.00147)
    // gain$=97.32/6.62 lots/147 points=$0.10/point or $1.00/pip.
    // IBFX demo/standard   EURUSD TICKVALUE=1.0 MAXLOT=50 LOTSIZE=100,000
    //                                  $1.00/point or $10.00/pip.
    // at.risk / maxLossPerLot = number of lots wanted. Must be
    // rounded/truncated to nearest lotStep size, still.
    //
    // However, the broker doesn't care about the at.risk/account balance. They
    // care about margin. margin used=lots used*marginPerLot and that must be
    // less than free margin available.
            marginFree   = AccountFreeMargin(),
            marginPerLot = MarketInfo( Symbol(), MODE_MARGINREQUIRED ),
    // So I use, the lesser of either.
            size = MathMin(marginFree / marginPerLot, at.risk / maxLossPerLot);
    /*---- Compute lot size based on account balance and MM mode*/}

    /*++++ Combine TSSF and trade size*/{
    if (size < minLot){ // Multiple orders -> no free margin
            // [risk=9.48USD/40.80, margin=10.62/1334.48, MMM=1x1, ExtraOO=0]
            //       0.23                  0.007
        Print(
            "LotSize(SL=", DoubleToStr(SL_points/pips2dbl, Digits.pips), ")=",
            size, " [risk=", at.risk, AccountCurrency(),    "/", maxLossPerLot,
                    ", margin=",    marginFree,             "/", marginPerLot,
                    ", MMM=",       MMMode_F0M1G2,          "x", MMMultplier,
                    ", ExtraOO=",   OrdersTotal()-oo.count,
                "]" );
        return(0.0);    // Risk limit.
    }
    double  LotStep = MarketInfo(Symbol(), MODE_LOTSTEP),
            adjFact = MathMin(1,(TSSF-1)/(TSSF.Max-1));
    size =  MathMax(minLot, MathFloor(size*adjFact/ LotStep)*LotStep);
    /*---- Combine TSSF and trade size*/}
    at.risk = size * maxLossPerLot; // Export for Comment
    return(size);
}   // LotSize
 

engcomp: Now go and pick the WORST period. If you still get positive TEF instead of negative, you have hit pay-dirt. 

I tried to find the worse period by looking at the report form 1999-now. I actually did find that time in December of 1999 when it lost 10 trades in a row. So instead of writing down the results of 20 trades and averaging them, I decided I'll let the back-tester do the work by enter that time frame. However, the results were totally positive and different and I should have expected that because my system looks at history sometimes to determine the direction of a new trade.

 

However, I decided to just keep going 2 weeks back from recent times until I  found really bad result. I didn't have to look too far. From 6/6/2010 to 6/20/2010. It generated 22 trades, here are the results :(

win% 36
AvgWin 52
AvgLoss 65
Real_R 0.8
Zero_R 1.777777778
Safe_R 3.846153846
TEF -0.472727273
 

 
WHRoeder:

I don't know yet how my approach compares to TEF.

Yes I update TSSF dropping off result 21 with two differences.
  1. I adjust the lot size instead of the account balance. This allows me to differentiate lack of margin (stacking a second order on small account) vs low TSSF. If there is sufficient margin, then I want to trade at least minlot to avoid a low TSSF from stopping all trading and essentially shutting the EA down.
  2. Initially I have no historical trades so I want to trade the minimum, but I didn't want to have to trade all 20 before starting to use TSSF. Also if the EA isn't trading much and the Terminal is set to only show one month of history or a small custom period, then there may never be 20 trades in history! So I add some equal wins and losses to make 20 so TSSF starts at 1 and slowly ramps to the actual value. This avoids the case where one win bumps TSSF up and the next trade is a looser with a large lot size. AveW/AveL is then hosed until it gets bumped.


WHR, thank you very much for the two functions.

I really appreciate the code. It's easy to change it for TEF as follows...
        else {                                                          double
            WLRsafe     = (1.1-win.fraction)/(win.fraction-0.1)+1;
            WLRzero     = (1 - win.fraction)/win.fraction;
            TSSF        = WLR.actual/WLRsafe;               // Export to LotSize
            TEF         = (WLR.actual-WLRzero)/(WLRsafe-WLRzero);
        }   // win.fraction > 0.15
I notice that you put a period in some variable names. Does that do anything special or is it just a name like any other?
Reason: