Walk-forward optimization library for MetaTrader: Estimator formula

15 August 2016, 19:42
Stanislav Korotky
0
826

This post is a part of documentation of WalkForwardOptimizer library for MetaTrader4/5 - here is the table of contents.

Estimator formula reference

Expressions for performance estimator can contain the following variables:

NP - net profit

GP - gross profit

GL - gross loss

PF - profit factor

SHARPE - sharpe 

TRADES - number of trades

DDMAX - maximum drawdown

DDREL - maximum relative drawdown

WIN - number of winning trades

LOSS - number of losing trades

DEPOSIT - initial balance

AR - average return, i.e. average % of return on a deal (profit/loss amount divided by current balance, averaged on all trades) - this is a measure of balance curve slope, used in sharpe (MT5, version 1.6+)

STDEV - standard deviation of balance curve (MT5, version 1.6+)

All mathematical and logical operators are supported, as well as common functions such as abs, exp, max, min, pow, sqrt. Here is an example of expression for modified PROC (Pessimistic Return on Capital):

(GP * (1 - 1/sqrt(WIN + 1)) + GL * (1 + 1/sqrt(LOSS + 1))) + NP / TRADES


Starting from version 1.6 for MT5 the following option is available.

If required calculations can not be expressed with a formula, one may implement a custom callback of type (updated in 1.8):

typedef double (*FUNCPTR_WFO_CUSTOM)(const datetime startDate, const datetime splitDate, const double &map[/*WFO_STATS_MAP*/]);

in the expert adviser and pass it to the library via wfo_setCustomPerformanceMeter(FUNCPTR_WFO_CUSTOM funcptr). Then WFO will call it from OnTester with the dates and the map filled with actual data. The function should return a custom value for OnTester (TesterStatistics can not be used inside!).

The indices of the array "map" are defined by the following enum:

/**
 * Built-in enum with indices for WFO stats container.
 * All is calculated for in-sample range of dates.
 */
enum WFO_STATS_MAP
{
  WFO_STATS_NP,      // net profit
  WFO_STATS_GP,      // gross profit
  WFO_STATS_GL,      // gross loss
  WFO_STATS_PF,      // profit factor
  WFO_STATS_SHARPE,  // sharpe
  WFO_STATS_TRADES,  // N of trades
  WFO_STATS_DDMAX,   // max drawdown value
  WFO_STATS_DDREL,   // drawdown percent
  WFO_STATS_WIN,     // N of winning trades
  WFO_STATS_LOSS,    // N of losing trades
  WFO_STATS_DEPOSIT, // start deposit
  WFO_STATS_AR,      // average return (% of current balance)
  WFO_STATS_STDEV,   // standard deviation of balance curve
  WFO_STATS_MAP_SIZE
};

The list of supported variants corresponds to the variables names shown above.

Here is an example of usage:

double customEstimator(const datetime startDate, const datetime splitDate, const double &map[]) export
{
  // TesterStatistics should not be normally used in custom estimators,
  // it's used here for validation purpose only (to check in-sample profit provided by WFO library
  // by calculating it in alternative way as the total profit minus out-of-sample)
  double profit = TesterStatistics(STAT_PROFIT);

  HistorySelect(splitDate + 1, TimeCurrent());

  uint total = HistoryDealsTotal();
  ulong ticket = 0;
  double plus = 0, minus = 0;
  int win = 0, loss = 0;

  for(uint i = 0; i < total; i++)
  {
    if((ticket = HistoryDealGetTicket(i)) > 0)
    {
      if(HistoryDealGetInteger(ticket, DEAL_ENTRY) != DEAL_ENTRY_IN)
      {
        double p = HistoryDealGetDouble(ticket, DEAL_PROFIT)
                 + HistoryDealGetDouble(ticket, DEAL_SWAP)
                 + HistoryDealGetDouble(ticket, DEAL_COMMISSION);
        if(p >= 0)
        {
          plus += p;
          win++;
        }
        else
        {
          minus -= p;
          loss++;
        }
        profit -= p;
      }
    }
  }
  
  Print("WFO stats: in-sample profit=", (float)map[WFO_STATS_NP], " in-sample Ntrades=", map[WFO_STATS_TRADES]);
  Print("Custom stats: in-sample profit(check)=", (float)profit);
  Print("Custom stats (out-of-sample): PF=", (float)(minus > 0 ? plus / minus : 1000), " Nwin=", win, " Nloss=", loss);

  return profit;
}

.


Share it with friends: