Custom Optimization Criteria (Fitness Function)

// MultiCharts – Raising the Trading Standard                                           http://www.multicharts.com
//  Custom Optimization Criteria: Wrapping it up; Combining Custom Criteria and exporting for further analysis.
//  Source: http://www.multicharts.com/discussion/viewtopic.php?f=5&t=8838

/* Choose the objective function, the performance metric on which you want to perform the Genetic Optimization, below.
    Give the variable ‘myObjectiveFunction’ a number corresponding with your choice:
    1: Sunny Harris’ CPC Index;
    2: Robert Pardo’s Pessimistic Return on Margin (PROM);
    3: Robert Pardo’s Required Capital;
    4: Pessimistic Return On Required Capital (PRORC);
    5: Michael Harris’ Probability Rule.

    For example, if you’d like to optimize on the CPC Index, give variable ‘myObjectiveFunction’ a value of 1.
*/
var myObjectiveFunction = 1;

/* Settings start here; change these to your preferences */
    /*  Change the variable ‘myFileLocation’ to the location to where you want to write your file. 
        Note: Before running a new optimization, you’ll need to remove, rename or delete this file. 
        Else it will get overwritten and/or will the header of the text file be unsuitable for importing in Excel.
    */
var myFileLocation = « c:\\Temp\\CustomCriteria_Output.txt »;
var AccountSize = 100000;
var SafetyFactor = 3.00;            // The SafetyFactor times the MaxDrawDown gives a buffer for the Required Capital.
var CapitalStopLoss = 0.40;         // The percentage loss after which you’ll stop trading the strategy (0.40 = 40%).
var TargetedProfitFactor = 2.00;    // The Profit Factor the trader want to achieve.
var CommissionPenalty = 0.60;       // Penalty used to calculate if the Profit Factor is achieved; enter a one (1) here to disable this.

/*
                This is the end of the settings
                        The code below can be left untouched
*/

// Strategy performance variables
var avgWinTrade         = StrategyPerformance.AvgWinningTrade;
var avgLoseTrade        = StrategyPerformance.AvgLosingTrade;
var percentProfitable   = StrategyPerformance.PercentProfitable;
var profitFactor        = StrategyPerformance.GrossProfit / Math.abs(StrategyPerformance.GrossLoss);
var winLossRatio        = StrategyPerformance.AvgWinningTrade / Math.abs(StrategyPerformance.AvgLosingTrade);
var numWinningTrades    = StrategyPerformance.WinningTrades;
var numLosingTrades     = StrategyPerformance.LosingTrades;
var maxDrawdown         = StrategyPerformance.MaxStrategyDrawDown;
var grossProfit         = StrategyPerformance.GrossProfit;
var grossLoss           = StrategyPerformance.GrossLoss;
var netProfit           = StrategyPerformance.NetProfit;
var numOfTrades         = StrategyPerformance.TotalTrades;
var avgTrade            = StrategyPerformance.AvgTrade;
var maxConsWins         = StrategyPerformance.MaxConsecWinners;
var maxConsLoss         = StrategyPerformance.MaxConsecLosers;
var avgBarWinner        = StrategyPerformance.AvgBarsInWinningTrades;
var avgBarLoser         = StrategyPerformance.AvgBarsInLosingTrades;
var returnOnAcc         = StrategyPerformance.ReturnOnAccount;
var returnOnAccSize     = (netProfit / AccountSize) * 100;              // Percentage profit on the AccountSize provided by the user
var maxDDPerc           = (maxDrawdown / AccountSize) * 100;            // The MaxDrawDown in percentage

// Objective functions variables
var cpcIndex, prom, reqCapital, prorc, reqProfitability, headerString, outputString, sep;

var sqrtWins            = Math.sqrt(numWinningTrades);
var sqrtLosses          = Math.sqrt(numLosingTrades);
var pessResult          = (avgWinTrade * (numWinningTrades – sqrtWins)) – (Math.abs(avgLoseTrade) * (numLosingTrades + sqrtLosses));

sep = « ; »;          // The seperator between values exported in the text file; change this if you have trouble importing the data with your Locale/Region settings
var decimals = 4;       // Number of decimals to export 
var curDecimals = 2;    // Number of decimals for currency values

/* The calculation of the Custom Criteria starts below */

// Sunny Harris’ CPC Index
if (avgWinTrade == 0 || avgLoseTrade == 0) {
    cpcIndex = 0;
}
else {
    cpcIndex = (percentProfitable / 100) * winLossRatio * profitFactor;
}

// Robert Pardo’s Pessimistic Return on Margin (PROM)
if (AccountSize < 1 || numWinningTrades == 0 || numLosingTrades == 0) {
    prom = 0;
}
else {
    prom = (pessResult / AccountSize) * 100; 
}

// Robert Pardo’s Required Capital
if (CapitalStopLoss < 0.01 || SafetyFactor < 0.01 || maxDrawdown == 0) {
    reqCapital = 0;
}
else {
    reqCapital = (Math.abs(maxDrawdown) * SafetyFactor) / CapitalStopLoss;
}

// Pessimistic Return On Required Capital (PRORC); inspired on Pardo’s concepts
if (prom == 0 || reqCapital == 0) {
    prorc = 0;
}
else {
    prorc = (pessResult / reqCapital) * 100;
}

// Michael Harris’ Probability Rule
if (TargetedProfitFactor < 0.01 || CommissionPenalty < 0 || CommissionPenalty > 1) {
    reqProfitability = 0;
}
else {
    reqProfitability = percentProfitable – (TargetedProfitFactor / (TargetedProfitFactor + (CommissionPenalty * winLossRatio)) * 100);
}

// Function to print the data to the file
function WriteToFile(stringToWrite) {
    // Create a new FileSystemObject 
    fsObj = new ActiveXObject(« Scripting.FileSystemObject »);

    // If the file doesn’t exits, create it, write the header {and the first line}
    if (!fsObj.FileExists(myFileLocation)) {
       
        // Create the header string
        headerString = 
            « CPC Index »             + sep +
            « PROM »                  + sep +
            « RequiredCapital »       + sep +
            « PRORC »                 + sep +
            « ProbabilityRule »       + sep +
            « GrossProfit »           + sep +
            « GrossLoss »             + sep +
            « NetProfit »             + sep +
            « ReturnOnAccount »       + sep +
            « ReturnOnAccountSize »   + sep +
            « PessimisticProfit »     + sep +
            « TotalTrades »           + sep +
            « PercentProfitable »     + sep +
            « WinningTrades »         + sep +
            « LosingTrades »          + sep +
            « AvgTrade »              + sep +
            « AvgWinningTrade »       + sep +
            « AvgLosingTrade »        + sep +
            « WinLossRatio »          + sep +
            « ProfitFactor »          + sep +
            « MaxStrategyDrawDown »   + sep +
            « MaxDrawDownPercentage » + sep +
            « MaxConsecWinners »      + sep +
            « MaxConsecLosers »       + sep +
            « AvgBarsInWinningTrades »+ sep +
            « AvgBarsInLosingTrades »
            ;

        // Create the file
        fsObj.CreateTextFile(myFileLocation);

        // Open stream to write to it
        os = fsObj.GetFile(myFileLocation);
        os = os.OpenAsTextStream(2, 0);

        // Write data to it
        os.WriteLine(headerString);
        //os.WriteLine(stringToWrite);

        // Close the file
        os.Close();
    }
    else {
        os = fsObj.GetFile(myFileLocation);
        os = os.OpenAsTextStream(8, 0);

        os.WriteLine(stringToWrite);

        os.Close();
    }
}

// Create the string with strategy data
outputString =
    cpcIndex.toFixed(decimals)              + sep +
    prom.toFixed(decimals)                  + sep +
    reqCapital.toFixed(curDecimals)         + sep +
    prorc.toFixed(decimals)                 + sep +
    reqProfitability.toFixed(decimals)      + sep +
    grossProfit.toFixed(curDecimals)        + sep +
    grossLoss.toFixed(curDecimals)          + sep +
    netProfit.toFixed(curDecimals)          + sep +
    returnOnAcc.toFixed(decimals)           + sep +
    returnOnAccSize.toFixed(decimals)       + sep +
    pessResult.toFixed(curDecimals)         + sep +
    numOfTrades.toFixed(0)                  + sep +
    percentProfitable.toFixed(decimals)     + sep +
    numWinningTrades.toFixed(0)             + sep +
    numLosingTrades.toFixed(0)              + sep +
    avgTrade.toFixed(decimals)              + sep +
    avgWinTrade.toFixed(decimals)           + sep +
    avgLoseTrade.toFixed(decimals)          + sep +
    winLossRatio.toFixed(decimals)          + sep +
    profitFactor.toFixed(decimals)          + sep +
    maxDrawdown.toFixed(curDecimals)        + sep +
    maxDDPerc.toFixed(decimals)             + sep +
    maxConsWins.toFixed(0)                  + sep +
    maxConsLoss.toFixed(0)                  + sep +
    avgBarWinner.toFixed(decimals)          + sep +
    avgBarLoser.toFixed(decimals)
    ;

WriteToFile(outputString);

// Return the choosen objective function
if (myObjectiveFunction == 1) {
    return cpcIndex;
}
else if (myObjectiveFunction == 2) {
    return prom;
}
else if (myObjectiveFunction == 3) {
    return reqCapital;
}
else if (myObjectiveFunction == 4) {
    return prorc;
}
else if (myObjectiveFunction == 5) {
    return reqProfitability;
}
else {      // makes sure that at least something gets returned
    return netProfit;
}


About this entry