OMX_F_GPF (Series Function)
Previous  Top  Next

Summary:
OMX_F_GPF is a customizable fitness function that measures and combines several fitness components into a compound value. Call this function in the Epilog to compute a fitness value.


 
clip0008Ease-of-use Tip  
Sample code for using this function is available within TradeStation in strategies OMX_CutAndPaste and OMX_Sample1_C. Simply open one of those strategies and cut and paste the sample code into your own strategy to use.  
 
 

Prototype:
 
OMX_Fitness = OMX_F_GPF(   
   OMX_IterationNum,          { The Optimax Iteration Number                                    }  
   PrintInfo,                 { 1=print detail info to the output window, 2=\GPF.txt 0=don't    }  
   SendVarsToOMX,             { true=call OMX_SendVar for each of the intermediate values       }  
   RejectNegNetProfit,        { Always reject a negative net profit value?                      }  
   PeriodType,                { 1 = day, 2 = week, 3 = month                                    }  
   InvestmentCapital,         { Available Investment Capital (in $)                             }  
                              {--- Avg Number of Trades Per Period                            --}  
   ATP_Tgt,                   { Target # of trades per period                                   }  
   ATP_Wgt,                   { Weighting factor                                                }  
   ATP_Rng,                   { Acceptable +/- Range                                            }  
   ATP_Bal,                   { Balance between SSDev and Proximity (1 to 0)                    }  
   ATP_TLT,                   { Time-line Scaling Type (1=Linear, 2=Exponential)                }  
   ATP_TLW,                   { Time-line Scaling Weighting factor (0 to +/-N.N)                }  
   ATP_Pos,                   { Use positive values only? (Ignore negatives?)                   }  
                              {--- Pct Profitable Trades                                      --}  
   PPT_Tgt,                   { Target Pct Profitable trades per period 1 = 1%, 80 = 80%        }  
   PPT_Wgt,                   { Weighting factor                                                }  
   PPT_Rng,                   { Acceptable Range                                                }  
   PPT_Bal,                   { Balance between SSDev and Proximity (1 to 0)                    }  
   PPT_TLT,                   { Time-line Scaling Type (1=Linear, 2=Exponential)                }  
   PPT_TLW,                   { Time-line Scaling Weighting factor (0 to +/-N.N)                }  
   PPT_Pos,                   { Use positive values only? (Ignore negatives?)                   }  
                              {--- Average Bars Per Trade                                     --}  
   ABT_Tgt,                   { Target number of bars per trade                                 }  
   ABT_Wgt,                   { Weighting factor                                                }  
   ABT_Rng,                   { Acceptable +/- Range                                            }  
   ABT_Bal,                   { Balance between SSDev and Proximity (1 to 0)                    }  
   ABT_TLT,                   { Time-line Scaling Type (1=Linear, 2=Exponential)                }  
   ABT_TLW,                   { Time-line Scaling Weighting factor (0 to +/-N.N)                }  
   ABT_Pos,                   { Use positive values only? (Ignore negatives?)                   }  
                              {--- Bars Per Winning Trade/Bars Per Losing Trade Ratio         --}  
   BTR_Tgt,                   { Target ratio of bars per winning trade to bars per losing trade }  
   BTR_Wgt,                   { Weighting factor                                                }  
   BTR_Rng,                   { Acceptable +/- Range                                            }  
   BTR_Bal,                   { Balance between SSDev and Proximity (1 to 0)                    }  
   BTR_TLT,                   { Time-line Scaling Type (1=Linear, 2=Exponential)                }  
   BTR_TLW,                   { Time-line Scaling Weighting factor (0 to +/-N.N)                }  
   BTR_Pos,                   { Use positive values only? (Ignore negatives?)                   }  
                              {--- Avg % of Capital Invested Per Period                       --}  
   ACI_Tgt,                   { Target avg % of capital invested                                }  
   ACI_Wgt,                   { Weighting factor                                                }  
   ACI_Rng,                   { Acceptable +/- Range                                            }  
   ACI_Bal,                   { Balance between SSDev and Proximity (1 to 0)                    }  
   ACI_TLT,                   { Time-line Scaling Type (1=Linear, 2=Exponential)                }  
   ACI_TLW,                   { Time-line Scaling Weighting factor (0 to +/-N.N)                }  
   ACI_Pos,                   { Use positive values only? (Ignore negatives?)                   }  
                              {--- Max % of Capital Invested Per Period (can use for margin)  --}  
   MCI_Tgt,                   { Target max % of capital invested                                }  
   MCI_Wgt,                   { Weighting factor                                                }  
   MCI_Rng,                   { Acceptable +/- Range                                            }  
   MCI_Bal,                   { Balance between SSDev and Proximity (1 to 0)                    }  
   MCI_TLT,                   { Time-line Scaling Type (1=Linear, 2=Exponential)                }  
   MCI_TLW,                   { Time-line Scaling Weighting factor (0 to +/-N.N)                }  
   MCI_Pos,                   { Use positive values only? (Ignore negatives?)                   }  
                              {--- Average Win / Avg Loss Ratio - maximized                   --}  
   AWL_Wgt,                   { Weighting factor                                                }  
   AWL_TLT,                   { Time-line Scaling Type (1=Linear, 2=Exponential)                }  
   AWL_TLW,                   { Time-line Scaling Weighting factor (0 to +/-N.N)                }  
   AWL_Pos,                   { Use positive values only? (Ignore negatives?)                   }  
                              {--- Profit Factor - maximize                                   --}  
   PRF_Wgt,                   { Weighting factor                                                }  
   PRF_TLT,                   { Time-line Scaling Type (1=Linear, 2=Exponential)                }  
   PRF_TLW,                   { Time-line Scaling Weighting factor (0 to +/-N.N)                }  
   PRF_Pos,                   { Use positive values only? (Ignore negatives?)                   }  
                              {--- NetProfit to MaxDrawdown Ratio                             --}  
   NMR_Wgt,                   { Weighting factor                                                }  
   NMR_Pos,                   { Use positive values only? (Ignore negatives?)                   }  
 
   bDoComputation,            { Only compute when this value is True. usually LastBarOnChart    }  
 
   PeriodReturn,              { Equity Return in each period                                    }  
   PeriodTrades,              { Number of trades in each period                                 }  
   PeriodWins,                { Number of wins in each period                                   }  
   PeriodLosses,              { Number of losses in each period                                 }  
   PeriodPctPft,              { Percent profitable by period                                    }  
   PeriodGrossProfit,         { Gross profit by period                                          }  
   PeriodGrossLoss,           { Gross loss by period                                            }  
   PeriodProfitFactor,        { Profit Factor by period                                         }  
   PeriodEvenBars,            { Total bars in even trades by period                             }  
   PeriodWinBars,             { Total bars in winning trades by period                          }  
   PeriodLosBars,             { Total bars in losing trades by period                           }  
   PeriodTotalTrades,         { Total number of trades by period                                }  
   PeriodABT,                 { Period average bars per trade                                   }  
   PeriodAWL,                 { Avg Win/Loss per period                                         }  
   PeriodBTR,                 { AB Win/AB Loss ratio per period                                 }  
   PeriodACI,                 { Avg % of capital invested per period                            }  
   PeriodMCI ;                { Max % of capital invested per period                            }  

Parameters:

Name
Type
Possible Values
Description
OMX_IterationNum
NumericSimple
Any integer
The Optimax iteration number
PrintInfo
NumericSimple
0,1,2
When 1, this function prints detailed information about the internal computations to the TradeStation Output Print Log window. This information is useful for tuning the weighting parameters and for determining the optimum size of the input arrays. When 2, the same information is printed to file \GPF.txt (in the root directory,) instead. When 0, no information is printed.
SendVarsToOMX
TrueFalseSimple
True/False
When True, this function sends information about internal computations to the Optimax Performance Detail Report. This information is useful for tuning the weighting parameters.
RejectNegNetProfit
TrueFalseSimple
True/False
When True, equity curves which end with a negative Net Profit will always have a negative fitness value. When False, only the potential for generating positive equity across the entire curve determines the sign of the return value, not the final value of the equity.
PeriodType
NumericSimple
1, 2, 3
The length of period to use for internal consistency measurements. 1=daily, 2=weekly, 3=monthly
InvestmentCapital
NumericSimple
any positive value
The amount of capital available to invest, in dollars. Used for computing the ACI and MCI component values.
ATP_Tgt
NumericSimple
any positive value
The average number of trades per period that you would like to target during optimization.
ATP_Wgt
NumericSimple
0 to any number usually 0 to 1.0
The weighting factor (importance) of the ATP component relative to all other components.
ATP_Rng
NumericSimple
0 to any number
The acceptable size of the range on either side of the ATP_Tgt.
ATP_Bal
NumericSimple
1.0 to 0.0
The balance between SSDev and Proximity importance.
ATP_TLT
NumericSimple
1,2
The Time-line scaling type. 1=Linear, 2=Exponential
ATP_TLW
NumericSimple
+/-n.n
The Time-line scaling weighting factor.
ATP_Pos
TrueFalseSimple
True/False
Use positive values only, meaning convert negative values to 0, so that they do not subtract from the fitness of other components.
PPT_Tgt
NumericSimple
any positive value
The average percent profitable trades per period that you would like to target during optimization.
PPT_Wgt
NumericSimple
0 to any number usually 0 to 1.0
The weighting factor (importance) of the PPT component relative to all other components.
PPT_Rng
NumericSimple
0 to any number
The acceptable size of the range on either side of the PPT_Tgt.
PPT_Bal
NumericSimple
1.0 to 0.0
The balance between SSDev and Proximity importance.
PPT_TLT
NumericSimple
1,2
The Time-line scaling type. 1=Linear, 2=Exponential
PPT_TLW
NumericSimple
+/-n.n
The Time-line scaling weighting factor.
PPT_Pos
TrueFalseSimple
True/False
Use positive values only, meaning convert negative values to 0, so that they do not subtract from the fitness of other components.
ABT_Tgt
NumericSimple
any positive value
The average bars per trade per period that you would like to target during optimization.
ABT_Wgt
NumericSimple
0 to any number usually 0 to 1.0
The weighting factor (importance) of the ABT component relative to all other components.
ABT_Rng
NumericSimple
0 to any number
The acceptable size of the range on either side of the ABT_Tgt.
ABT_Bal
NumericSimple
1.0 to 0.0
The balance between SSDev and Proximity importance.
ABT_TLT
NumericSimple
1,2
The Time-line scaling type. 1=Linear, 2=Exponential
ABT_TLW
NumericSimple
+/-n.n
The Time-line scaling weighting factor.
ABT_Pos
TrueFalseSimple
True/False
Use positive values only, meaning convert negative values to 0, so that they do not subtract from the fitness of other components.
BTR_Tgt
NumericSimple
any positive value
The average per period of winning bars per trade to losing bars per trade that you would like to target during optimization.
BTR_Wgt
NumericSimple
0 to any number usually 0 to 1.0
The weighting factor (importance) of the BTR component relative to all other components.
BTR_Rng
NumericSimple
0 to any number
The acceptable size of the range on either side of the BTR_Tgt.
BTR_Bal
NumericSimple
1.0 to 0.0
The balance between SSDev and Proximity importance.
BTR_TLT
NumericSimple
1,2
The Time-line scaling type. 1=Linear, 2=Exponential
BTR_TLW
NumericSimple
+/-n.n
The Time-line scaling weighting factor.
BTR_Pos
TrueFalseSimple
True/False
Use positive values only, meaning convert negative values to 0, so that they do not subtract from the fitness of other components.
ACI_Tgt
NumericSimple
any positive value
The average percentage of capital invested per period that you would like to target during optimization.
ACI_Wgt
NumericSimple
0 to any number usually 0 to 1.0
The weighting factor (importance) of the ACI component relative to all other components.
ACI_Rng
NumericSimple
0 to any number
The acceptable size of the range on either side of the ACI_Tgt.
ACI_Bal
NumericSimple
1.0 to 0.0
The balance between SSDev and Proximity importance.
ACI_TLT
NumericSimple
1,2
The Time-line scaling type. 1=Linear, 2=Exponential
ACI_TLW
NumericSimple
+/-n.n
The Time-line scaling weighting factor.
ACI_Pos
TrueFalseSimple
True/False
Use positive values only, meaning convert negative values to 0, so that they do not subtract from the fitness of other components.
MCI_Tgt
NumericSimple
any positive value
The maximum percentage of capital invested on average per period that you would like to target during optimization.
MCI_Wgt
NumericSimple
0 to any number usually 0 to 1.0
The weighting factor (importance) of the MCI component relative to all other components.
MCI_Rng
NumericSimple
0 to any number
The acceptable size of the range on either side of the MCI_Tgt.
MCI_Bal
NumericSimple
1.0 to 0.0
The balance between SSDev and Proximity importance.
MCI_TLT
NumericSimple
1,2
The Time-line scaling type. 1=Linear, 2=Exponential
MCI_TLW
NumericSimple
+/-n.n
The Time-line scaling weighting factor.
MCI_Pos
TrueFalseSimple
True/False
Use positive values only, meaning convert negative values to 0, so that they do not subtract from the fitness of other components.
AWL_Wgt
NumericSimple
0 to any number usually 0 to 1.0
The weighting factor (importance) of the Average Win/Loss ratio (AWL component factor) relative to all other components.
AWL_TLT
NumericSimple
1,2
The Time-line scaling type. 1=Linear, 2=Exponential
AWL_TLW
NumericSimple
+/-n.n
The Time-line scaling weighting factor.
AWL_Pos
TrueFalseSimple
True/False
Use positive values only, meaning convert negative values to 0, so that they do not subtract from the fitness of other components.
PRF_Wgt
NumericSimple
0 to any number usually 0 to 1.0
The weighting factor (importance) of the profit factor (PRF component value) relative to all other components.
PRF_TLT
NumericSimple
1,2
The Time-line scaling type. 1=Linear, 2=Exponential
PRF_TLW
NumericSimple
+/-n.n
The Time-line scaling weighting factor.
PRF_Pos
TrueFalseSimple
True/False
Use positive values only, meaning convert negative values to 0, so that they do not subtract from the fitness of other components.
NMR_Wgt
NumericSimple
0 to any number usually 0 to 1.0
The weighting factor (importance) of the net profit to intraday drawdown ratio (NMR component value) relative to all other components.
NMR_Pos
TrueFalseSimple
True/False
Use positive values only, meaning convert negative values to 0, so that they do not subtract from the fitness of other components.
bDoComputation
TrueFalseSimple
True/False
When true, compute the return (fitness) value. Usually passed a variable that is true on the final bar of analysis - usually LastBarOnChart
PeriodReturn
NumericArrayRef
Output only
Equity Return in each period
PeriodTrades
NumericArrayRef
Output only
Number of trades in each period
PeriodWins
NumericArrayRef
Output only
Number of wins in each period
PeriodLosses
NumericArrayRef
Output only
Number of wins in each period
PeriodPctPft
NumericArrayRef
Output only
Percent profitable by period
PeriodGrossProfit
NumericArrayRef
Output only
Gross profit by period
PeriodGrossLoss
NumericArrayRef
Output only
Gross loss by period
PeriodProfitFactor
NumericArrayRef
Output only
Profit Factor by period
PeriodEvenBars
NumericArrayRef
Output only
Total bars in even trades by period
PeriodWinBars
NumericArrayRef
Output only
Total bars in winning trades by period
PeriodLosBars
NumericArrayRef
Output only
Total bars in losing trades by period
PeriodTotalTrades
NumericArrayRef
Output only
Total number of trades by period
PeriodABT
NumericArrayRef
Output only
Period average bars per trade
PeriodAWL
NumericArrayRef
Output only
Period average win/loss ratio
PeriodBTR
NumericArrayRef
Output only
Avg Bars Win/Avg Bars Loss ratio per period
PeriodACI
NumericArrayRef
Output only
Avg % of capital invested per period
PeriodMCI
NumericArrayRef
Output only
Max % of capital invested per period
 


 
Function Type: Series
This is a series function - it executes at the end of the every bar.

Returns (Double)
This function returns a floating-point value which can be negative or positive, with values above 0 indicating desirable fitness and values 0 or below indicating undesirable fitness.

Description and Use
This function creates a compound, comprehensive fitness value from several discrete components. It is compatible with any type of strategy. Use it when you want to achieve fitness objectives other than a simple maximum net profit.

Notes  
·Within this document the term GPF refers to this function and the output from it.  
·Be sure to read the Period Arrays section below before attempting to use this function.  
 
Introduction  
This is not a "black box" fitness function as most are. This function is parametric, meaning it requires you to specify several input parameters. The output value depends upon the input parameter settings. In order to use this function successfully and to obtain the desired results, you are required to understand the correct use of the inputs. So instead of using many different fitness functions that contain components in a predefined static configuration, this one is flexible in that you can customize it by specifying parameter combinations to emphasize varying aspects of fitness and so customize the function according to the type of chart, type of strategy and your personal fitness goals.  
 
Parameters and Components  
Within this function are discrete internal computations, known as internal components. Input parameters control this internal fitness components, and are as follows:  
 
Component (per period)
Specifiable Parameters
Number of Trades Per Period
Target value, Weight, Range, Timeline Scaling, Pos-Only
Percent Profitable Trades
Target value, Weight, Range, Timeline Scaling, Pos-Only
Number of Bars per Trade
Target value, Weight, Range, Timeline Scaling, Pos-Only
Win/Loss Trade Bars Ratio
Target value, Weight, Range, Timeline Scaling, Pos-Only
Avg % of Capital Invested
Target value, Weight, Range, Timeline Scaling, Pos-Only
Max % of Capital Invested
Target value, Weight, Range, Timeline Scaling, Pos-Only
Avg Win/Avg Loss Ratio
Weight, Timeline Scaling, Pos-Only (value is always maximized)
Profit Factor
Weight, Timeline Scaling, Pos-Only (value is always maximized)
NetProfit to Max IDD Ratio
Weight, Timeline Scaling, Pos-Only (value is always maximized)
 
 
The final GPF value is the sum of the internal component values, as shown here:  
 
GPF = ATP + PPT + ABT + AWL + BTR + ACI + MCI + PRF + NMR  
where:  
ATP   is Average Number of Trades per period  
PPT   is Percent Profitable Trades  
ABT   is Average number of bars per trade  
AWL   is Average Win/Average Loss ratio  
BTR   is Win Bars Per Trade/Loss Bars per Trade Ratio  
ACI   is Avg % of Capital Invested  
MCI   is Max % of Capital Invested  
PRF   is Profit Factor  
NMR   is NetProfit to Max IDD Ratio  
GPF   is the output value from this fitness function  
 
Subcomponents  
Each component is built from several subcomponents, as follows:  
 
·The raw component value  
·The weighting factor you specify for the component  
·The proximity to the target you specify for the component  
·The measure of uniformity of the raw component values on a per-period basis (This is referred to the SSDev value in the subsequent documentation.)  
 
GPF combines subcomponent values together to obtain a final component value, according to the following equation:  
 
CFinal = ( ( CRaw * (1-CBal) * CProximity ) + ( CRaw * CBal * CSSDev) ) * CWeight  
 
where:  
CFinal   is the final value for the component  
CRaw   is the raw (average per period) subcomponent value  
CBal      is the balance between the importance of the SSDev and Proximity subcomponents  
CProximity   is the proximity to target subcomponent value  
CSSDev   is the SSDev (measure of uniformity) subcomponent value  
CWeight   is the weighting specified by you for the subcomponent  
 
For example, to obtain the Percent Profitable Trades component final value:  
 
PPT_Final = ( XOrNegProduct( PPT_Raw * (1-PPT_Bal), PPT_Proximity ) + XOrNegProduct( PPT_Raw * PPT_Bal, PPT_SSDev) ) * PPT_Weight  
 
This calculation takes a portion of the Raw value and weights it by proximity. It then takes the remaining portion of the Raw value and weights it by uniformity per period. It adds the two weighted portions together and then weights the entire sum by the weighting factor you specified for the subcomponent. A perfect score for a subcomponent is 1, provided the maximum weighting value you use is 1.  
 
If you specify a balance (PPT_Bal) value of 0.5, then the proximity to target is equally as important as the uniformity per period. You can adjust this by altering the balance value. For example, setting balance to 0.8 causes 80% of the importance to be placed on the uniformity, and only 20% on the proximity to target. Setting balance to 1 causes only uniformity to be considered. Setting it to 0 causes only proximity to target to be considered.  
 
If either the Raw or the Proximity value or BOTH are negative, the result of the multiplication is negative. This is accomplished via the XOrNegProduct function. This also holds true for the Raw and SSDev values. This unique treatment of the product of values ensures that a negative portion of the component remains negative; if it didn't it would incorrectly increase the value of the subcomponent.  
 
If you have specified Positive Only = True for the component and the component's final value is negative, GPF sets the final value to 0. This causes negative values to be ignored instead of subtracting them from the final GPF. Use this option when you have fewer equity curves with positive values and you want to increase the diversity of the initial search space. If you have a majority of curves with positive GPF values, using Positive Only = False helps the GPF to concentrate on the most promising areas and should increase the rate of convergence.  
 
Component Weights  
When you call OMX_F_GPF, you specify weighting values for each component. These values can range from 0 to any number. If you set all weights to the same value (e.g. if you set them all to 1) then all components will be considered equal in weight. Usually, you would weight the profit factor highest, then percent profitable and/or NetProfit to MaxIDD ratio, then the rest below those. You can cause a component to be ignored completely by specifying a weighting factor of 0 for that component.  
 
Note that you will have to experiment with the weights in order to determine appropriate values. You will find that raw values can vary quite a bit from component to component, so you must use the weights to compensate for differences in raw values as well as to apply relative strength to each.  
 
Target Value and Range  
The target value enables you to specify what you consider to be an ideal value for one component. The range specifies the acceptable range of values from the target. If a value exceeds the target +/- the range, then the fitness will become negative and the individual will be rejected. The closer the value is to the target, the higher the resulting fitness value will be. Values at the edges of the range result in lower fitness values.  
 
For example, an ideal target value for Number of Bars per Trade on a 1-minute chart may be 10, within an acceptable range of +/-5, meaning that a test that results with Number of Bars Per Trade of 10 will have the highest fitness value. Tests that have values down to 6 and up to 14 will result in a positive fitness. Values at the edge of and outside of that range will result in a 0 or negative fitness.  
 
The GPF function computes the proximity of the a given value to the target value as follows:  
 
·a value that is 50% of the way to the edge of the range is a 50% (0.5) match  
·a value that is 25% of the way to the edge of the range is a 75% (0.75) match  
·a value that is equal to the target value is a perfect match (1.0)  
·a value that is 100% of the way to the edge of the range is a 0 match  
·a value that is greater than 100% away is a negative match  
 
So for example if the target is 10 bars per trade with a +/-5 range, then an 8-bar trade is a 0.6 match, a 6-bar trade is 0.2, a 10-bar trade is a 1 (perfect) match, a 12 is a 0.6 match, 14 is 0.2, 15 is 0, 16 is -0.2 etc.  
 
A range of < 1 presents special cases. Specifying a range of < 1 on any value that can only be an integer will result in the highest selectivity and will only pass a single value because any value that equals the target will a 100% match, and any other value will be a negative match.  
 
One may think that there should not be a specifiable target for Percent Profitable but rather it should always be maximized. That is fine - if you wish to alwaysmaximize it, set the target to 100. However, in real life it is impossible to achieve 100% profitable trades and any back-test that indicates 100% profitabletrades should thus be suspected of displaying strongly curve-fit results.A more realistic target would be 80% profitable trades. Specifying a targetof 80% will discount performance results about 80 and the closer they are to 100 the more they will be discounted, thus penalizing results according to their probability of being curve-fit. Doing this should yield more accurate optimization results.  
 
To minimize a value such as the Average Bars Per Trade, specify a target value of 1 and a Range equal to the maximum acceptable Average Bars Per Trade plus one.  
 
The RejectNegNetProfit Parameter  
If you specify the parameter RejectNegNetProfit = True, you can cause the GPF fitness to always be negative whenever the Net Profit of the back test is negative. This is a traditional approach because it seems intuitive that if the test lost money, then it would be undesirable. However, it could also be argued that if the test made money at some point, even though at the end it lost, then it contains some potential for making money and the fact that it lost at the end was only a co-incidence of the end-date for the test and a negative portion of the equity curve. To rephrase, if your end-date for the test had been different, then the NetProfit could have been positive and the result would not have been rejected. So using this GPF function you have the option to also consider curves that end in a negative NetProfit value that yet exhibit positive traits throughout much of the test period.  
 
Periodicity  
Periodicity is a key concept in this fitness function. It is built in to every component except the NMR component.  
 
Instead of using a single period for computing each value as most fitness functions do (that period being the duration of the back-test,) this function computes values on a per-period basis, and then averages them to obtain the raw subcomponent per component. You can specify that the period be daily, weekly or monthly using the PeriodType parameter, as follows:  
 
PeriodType
Period Length
1
day
2
week
3
month
 
 
GPF stores all historical values into separate a separate bin for each period and computes the consistency of the series of bin values. This measure of consistency is called the SSDev subcomponent. GPF uses the SSDev subcomponent value to weight the component in addition to using your weighting as well. For example, assume that in a particular back-test over 6 months there were 42 wins and 18 losses. The percent profitability is 70%. The ideal distribution of those trades is:  
 
Distribution 1  
Period
Wins
Losses
% Profitable

1
7
3
70

2
7
3
70

3
7
3
70

4
7
3
70

5
7
3
70

6
7
3
70


---
---
---


42
18
70%
Total % Profitable Trades
 
 
The above distribution is obviously more desirable than the one below, which also results in exactly 70% profitable trades, but only averages 20% per period.  
 
Distribution 2  
Period
Wins
Losses
% Profitable

1
1
9
10

2
0
0
0

3
1
4
20

4
40
4
91

5
0
0
0

6
0
1
0


---
---
---


42
18
70%
Total% Profitable Trades



20%
Average % Profitable Trades
 
 
Most fitness functions will see both of the above results as equally desirable, because they only look at the totals, not the distributions. The GPF function sees them differently. First instead of computing the percent profitable from the totals only, it computes percent profitable for each period separately and averages them. So the average percent profitable for the first series is 70%, whereas the average percent profitable for the second series is only 20%. GPF uses the average as the Raw subcomponent.  
 
Secondly, the GPF function also penalizes uneven distributions in addition to any penalty incurred from the averaging. This is done because averaging alone does not always penalize uneven distributions, as shown below.  
 
Distribution 3  
Period
Wins
Losses
% Profitable

1
6
4
60

2
8
2
80

3
1
1
100

4
3
2
80

5
3
0
60

6
3
1
40


---
---
---


24
11
69%
Total% Profitable Trades



70%
Average % Profitable Trades
 
 
Here we can see that a less-than-ideal distribution can actually result in a higher average than the simple total computation, and so needs to be penalized due to it's less-than ideal distribution. To penalize uneven distributions, GPF always computes a proprietary SSDev factor as shown here:  
 
SSDev = 1 - ( StdDev of PctProfitable per period / Avg PctProfitable per period )  
 
SSDev is the standard deviation of the percent variability of the value, standardized on a scale from 1 to -infinity, where 1 is no variability 0 is 100% variability, and -infinity is infinite variability.  
 
GPF multiplies the average value by the SSDev factor. If the distribution is perfect (as it was in Distribution 1,) then the SSDev factor will be 1, and so there is no penalty after multiplication. The more uneven the distribution, the lower the SSDev factor will be, and thus the higher the penalty.  
 
For example, computing the SSDev factor for Distribution 1 yields no penalty:  
StdDev = 0  
Avg = 70  
SSDev = 1 - ( 0 / 70 ) = 1  
Result: No penalty  
 
For Distribution 2, there is a heavy penalty:  
StdDev = 19.1  
Avg = 70  
SSDev = 1 - ( 19.1 / 70 ) = -0.625  
Result: Heavy penalty. The final GPF will be negative and so this individual will be entirely discarded.  
 
For Distribution 3, there is a minor penalty:  
StdDev = 32.5  
Avg = 70  
SSDev = 1 - ( 32.5 / 20 ) = 0.73  
Result: Minor penalty. The Percent Profitable component of the final GPF will be multiplied by 0.73 and so reduced by only 27%.  
 
GPF computes the average and SSDev values for all components of the GPF except the NMR (NetProfit to Max IDD Ratio.)  
 
When using this function as compared to other fitness functions, you will find that this function emphasizes consistency in all of the measurements. This should result in less scattering on the ISpace indicators and both fewer and narrower bands than with other fitness functions. The end result is a more clear indication of the input combinations that yield the targeted fitness values.  
 
Period Arrays  
GPF uses arrays to store the period bin values - one array element per bin. The speed of the function is directly proportional to the size of the arrays - the bigger the arrays, the slower the function will be. In order to enable you to maximize the speed of GPF, you define these arrays in your strategy and pass them to GPF. If you get an Array Out Of Bounds message from TradeStation when using GPF, then you need to increase the size of the arrays.  
 
Compute the necessary array size as follows:  
 
ArraySize = Number of Periods + 1  
 
So for example, if you are using daily periods and your are back testing over 100 days, then define the arrays as [101]. Set all GPF arrays to the same size.  
 
You can also determine how big the arrays should be by setting the PrintInfo parameter to True; GPF will print a message telling you the optimal array size. (See the section below on PrintInfo for more information on using this parameter.)  
 
Important Note on the use of Periods  
For period processing to be entirely accurate, you should ensure that the first period processed by your strategy begins on a period boundary, and the last period ends on a period boundary. For example, for type 1 (daily processing), you would ensure that the first bar processed by your strategy is the first bar of a day and the last bar is the final bar of a day. If your strategy starts processing the first day in the middle or ends in the middle then the period calculation for the first and/or final period will be incorrect, because the first and/or final period is not a full day. The same holds true for types 2 and 3, (weekly and monthly periods.) For type 2, you should ensure that your strategy processing begins on a Monday (if you're using weekly periods) and ends on a Friday or for type 3, on the 1st of a month and ends on the last day of a month.  
 
Starting the first period in the middle or at the end primarily affects the computation of the SSDev value (the uniformity measurement.) The extent of the effect is determined by the number of periods you process. The greater the number of periods you process, the less it will matter. For example, if you choose daily periods and have 200 of them in your back test, then you have at most only 1% error in your performance calculations if the first and last periods are not entire periods. If on the other hand you choose weekly periods and you process only 4 periods and the first one begins on a Friday, then you have introduced a 25% error margin into the fitness computation.  
 
A simple way to ensure that the first and last periods are fully processed to the boundaries you intend is to add code to your strategy to prevent processing before and/or after those points in time and then add an extra period to the beginning and end dates of the chart.  
 
Time-line Scaling  
GPF enables you to weight the importance of the results from recent periods more heavily than for older periods. For example, when you look at an equity curve, if the first part of the curve is good but the last part looses money you might say to yourself, "It would have been a good strategy a year ago, but lately it isn't doing well. The market has changed so I don't like this curve as much as one where performance was not as good a year ago, and is doing well lately." To this end, GPF includes Time-line scaling, meaning that you can cause measurements from recent periods to be more heavily weighted than measurements from earlier periods. You can specify the scaling type as linear or exponential, and a scaling weight factor. The higher the weight factor, the more important GPF considers recent period measurements.  
 
GPF applies time-line scaling to the Raw average value of the component, and to the SSDev value of the component, so both average and uniformity are scaled with time according to the scaling type and weight factor you specify.  
 
When you specify linear scaling, period values are scaled according to the following algorithm:  
 
for i = 1 to NumPeriods {  
Weight = Weight + ( ( i - 1 ) * AbsValue( WeightFactor ) ) ;  
WeightedSum = WeightedSum + ( Weight * PeriodValues[i] ) ;  
Divisor = Divisor + Weight ;  
}  
Result = WeightedSum / Divisor ;  
     
where:  
WeightFactor is the Time-line scaling weight factor you specify  
NumPeriods is the number of periods in the back-test  
PeriodValues is an array of the period values in the back-test  
 
When you specify exponential scaling, period values are scaled according to the following algorithm:  
 
for i = 1 to NumPeriods {  
Weight = Weight * AbsValue( WeightFactor ) ;  
WeightedSum = WeightedSum + ( Weight * PeriodValues[i] ) ;  
Divisor = Divisor + Weight ;  
}  
Result = WeightedSum / Divisor ;  
     
where:  
WeightFactor is the Time-line scaling weight factor you specify  
NumPeriods is the number of periods in the back-test  
PeriodValues is an array of the period values in the back-test  
 
 
For example, if you were to specify a scaling type of 1 (linear) and a factor of 1, recent periods would be considered more important than earlier periods. With a factor of 2 or 4, even more so. With a factor of 0.5, recent periods are considered only slightly more important. With a factor of 0, all periods would be evenly weighted and no time-line scaling would occur.  
 
If you were to specify a scaling type of 2 (exponential) instead, the scaling becomes exponential and tapers off much more quickly as you go backward in time. When using exponential scaling, a factor of 2 weights more recent results much more than for linear scaling. A factor of 1 causes even weighting to occur across all periods.  
 
To get a feel for the effects of time-line scaling, the following table illustrates some sample results.  
 
Assume there are 4 periods in the back test with period values of 1, 2, 3, 4:  
 
clip0025  
 
In the above chart, WSSDev is the weighted SSDev value. (The weighted SSDev value is used for all computations within the GPF function.)  
 
For another example, assume there are 10 periods in the back test with period values of 100, 90, 80, 70, 60, 50, 40, 30, 20, 10:  
 
clip0023  
 
Notice that exponential scaling affects the scaled standard deviation much more than linear scaling.  
 
Also notice that for weight factors between 0 and 1, exponential scaling causes earlier periods to be weighted more heavily than recent periods, but with linear scaling later periods are weighted more heavily than earlier periods. To invert the results for both scaling types, use a negative weighting factor. Negative weight factors cause earlier periods in time to be weighted more heavily than recent periods in the exact inverse proportion to the positive weighting factor of the same value.  
 
To turn time-line scaling off, use a Scale Type of 1 (linear) and a Factor of 0, or a Scale Type of 2 (exponential) and a Factor of 1. These settings cause measurements within all periods to be equally weighted.  
 
Capital Components  
The ACI component (Avg % of Capital Invested) and MCI component (Max % of Capital Invested) are useful for optimizing strategies that scale into and/or out of a position, or vary the number of shares invested. If you always use a fixed number of shares per trade and do not pyramid into or out of a position, set the ACI_Wgt and MCI_Wgt values to 0 to disable these components.  
 
However, if your positions can be different sizes, using ACI during optimization enables Optimax to favor input combinations within a target range of average % of capital invested. For example, if you want to discover inputs that favor an average of 80% of your capital invested at all times, you might trying specifying ACI_Tgt = 80 and ACI_Rng = 30 with an appropriate weighting, such as 0.25 to target 80% capital invested on average. Or, to favor input combinations that lower your average exposure, you might specify ACI_Tgt = 25 and ACI_Rng = 30 to target 25% capital invested on average.  
 
The MCI component (Max % of Capital Invested) is useful for optimizing strategies that take advantage of margin. For example, setting MCI_Tgt to 200 and the range to 200 causes this function to target an average maximum of 200% of capital invested, and all input combinations that result in an average maximum of over 400% to be rejected as unfit.  
 
When using these components, set the InvestmentCapital parameter equal to the initial investment capital you will use in real life.  
 
The PrintInfo and SendVarsToOMX Parameters  
Use these two parameters to display the intermediate results computed within GPF for all components and internal subcomponents. This is a very useful aid to assist you in adjusting the parameters to obtain the desired results.  
 
Setting the PrintInfo function to 1 will print detailed information about the fitness calculation to the EL Output window. To display this information within TradeStation, select View, EasyLanguage Output Bar, and click the Print Log tab at the bottom of the window. This information will display during an optimization, or if you copy the call to the GPF function to the end of your strategy then it will display during testing. (Be sure to remove or comment out the copy before beginning an optimization.)  
 
Setting this parameter to 2 will send the same information to a file instead. The file will be located in your root directory and it will be named GPF.txt.  
 
Setting it to 0 will turn this functionality off.  
 
Setting SendVarsToOMX to True will display the computation details within Optimax in the Detailed Performance Report pane.  
 
GPF Tuning  
To tune your weighting factors, run an optimization with SendVarsToOMX = True. Click sample equity curves in the Equity Grid and view the Detail Performance report at the bottom of the Optimax window. Examine the fitness values to determine which components are contributing the most to the GPF value, then adjust your weights to further emphasize or de-emphasize the components as desired.  
 
Note that you will have to experiment with the weights in order to determine appropriate values. You will find that raw values can vary quite a bit from component to component, so you will need to use the weights to compensate for differences in raw values as well as to apply relative strength to each.  
 
For example, you may find that one of the Raw values is extremely high compared to the rest, and so you may reduce the weighting on that component to bring it's contribution to the GPF into line with the rest. Or conversely, you may find that the Raw value for one of the components is very low compared to the rest. In that case, you may need to increase the weighting for that component to compensate for this imbalance.  

Examples
The following call computes the GPF based on monthly measurements. It handles up to 129 months in the back test, writes subcomponent information to \GPF.txt and to the performance report, always rejects a negative net profit, considers profit factor of highest importance, considers uniformity and proximity to target to be of equal importance for all subcomponents, and ignores both negative component values and capital components.

Arrays:  
   PeriodReturn[130](0),  
   PeriodTrades[130](0),  
   PeriodWins[130](0),  
   PeriodLosses[130](0),  
   PeriodPctPft[130](0),  
   PeriodGrossProfit[130](0),  
   PeriodGrossLoss[130](0),  
   PeriodProfitFactor[130](0),  
   PeriodEvenBars[130](0),  
   PeriodWinBars[130](0),  
   PeriodLosBars[130](0),  
   PeriodTotalTrades[130](0),  
   PeriodABT[130](0),  
   PeriodAWL[130](0),  
   PeriodBTR[130](0),  
   PeriodACI[130](0),  
   PeriodMCI[130](0) ;  
OMX_Fitness = OMX_F_GPF(   
    OMX_IterationNum, { Optimax Iteration number                   }  
                   2, { Write details to the Print Log or GPF.txt? }  
                true, { send variables to performance report       }  
                true, { Always reject a negative net profit value? }  
                   3, { Period Type: 1 = day, 2 = week, 3 = month  }  
              100000, { Available Investment capital               }  
    {--Weight, Target,  Range, Balance, TLT, TLW, PosOnly --} { TLT = Timeline weighting type, TLW = Timeline weighting scale factor }  
         0.10,     30,    30,  0.5,       2,   2, true, { # of trades per period:                           }  
         1.00,     80,    80,  0.5,       2,   2, true, { Pct Profitable trades per period (1 to 100%)      }  
         0.10,      1,    10,  0.5,       2,   2, true, { Average bars per trade                            }  
         0.50,      2,     4,  0.5,       2,   2, true, { Bars/winning trade:bars/losing trade ratio        }  
         0.00,     80,    80,  0.5,       2,   2, true, { Avg % of capital invested                         }  
         0.00,    200,   200,  0.5,       2,   2, true, { Max % of capital invested                         }  
         0.25,                            2,   2, true, { Win/Loss ratio (always maximized)                 }  
         1.00,                            2,   2, true, { Profit factor (always maximized)                  }  
         0.05,                                    true, { NetProfit to MaxDrawdown Ratio (always maximized) }  
    LastBarOnChart,                         { When to perform the computation                   }  
    { All Arrays }  
    PeriodReturn,              { Equity Return in each period           }  
    PeriodTrades,              { Number of trades in each period        }  
    PeriodWins,                { Number of wins in each period          }  
    PeriodLosses,              { Number of losses in each period        }  
    PeriodPctPft,              { Percent profitable by period           }  
    PeriodGrossProfit,         { Gross profit by period                 }  
    PeriodGrossLoss,           { Gross loss by period                   }  
    PeriodProfitFactor,        { Profit Factor by period                }  
    PeriodEvenBars,            { Total bars in even trades by period    }  
    PeriodWinBars,             { Total bars in winning trades by period }  
    PeriodLosBars,             { Total bars in losing trades by period  }  
    PeriodTotalTrades,         { Total number of trades by period       }  
    PeriodABT,                 { Period average bars per trade          }  
    PeriodAWL,                 { Avg Win/Loss per period                }  
    PeriodBTR,                 { AB Win/AB Loss ratio per period        }  
    PeriodACI,                 { Avg % of capital invested per period   }  
    PeriodMCI ) ;              { Max % of capital invested per period }  


Bar Validity
Valid on intraday, daily, weekly and monthly bars. Invalid on tick, volume and point & figure charts.

Notes
Do not pass the constant True
as the last parameter. Doing so will cause the calculation to be computed on every bar and significantly slow down your optimization.