OMX_F_GPF (Series Function)

Previous Top Next 


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, { Timeline Scaling Type (1=Linear, 2=Exponential) }

ATP_TLW, { Timeline 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, { Timeline Scaling Type (1=Linear, 2=Exponential) }

PPT_TLW, { Timeline 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, { Timeline Scaling Type (1=Linear, 2=Exponential) }

ABT_TLW, { Timeline 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, { Timeline Scaling Type (1=Linear, 2=Exponential) }

BTR_TLW, { Timeline 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, { Timeline Scaling Type (1=Linear, 2=Exponential) }

ACI_TLW, { Timeline 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, { Timeline Scaling Type (1=Linear, 2=Exponential) }

MCI_TLW, { Timeline 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, { Timeline Scaling Type (1=Linear, 2=Exponential) }

AWL_TLW, { Timeline Scaling Weighting factor (0 to +/N.N) }

AWL_Pos, { Use positive values only? (Ignore negatives?) }

{ Profit Factor  maximize }

PRF_Wgt, { Weighting factor }

PRF_TLT, { Timeline Scaling Type (1=Linear, 2=Exponential) }

PRF_TLW, { Timeline 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 }



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:




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 perperiod 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 * (1CBal) * 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 * (1PPT_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 1minute 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 8bar trade is a 0.6 match, a 6bar trade is 0.2, a 10bar 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 backtest that indicates 100% profitabletrades should thus be suspected of displaying strongly curvefit 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 curvefit. 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 coincidence of the enddate for the test and a negative portion of the equity curve. To rephrase, if your enddate 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 backtest,) this function computes values on a perperiod 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:




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 backtest over 6 months there were 42 wins and 18 losses. The percent profitability is 70%. The ideal distribution of those trades is:


Distribution 1



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



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



Here we can see that a lessthanideal distribution can actually result in a higher average than the simple total computation, and so needs to be penalized due to it's lessthan 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.


Timeline 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 Timeline 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 timeline 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 Timeline scaling weight factor you specify

NumPeriods is the number of periods in the backtest

PeriodValues is an array of the period values in the backtest


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 Timeline scaling weight factor you specify

NumPeriods is the number of periods in the backtest

PeriodValues is an array of the period values in the backtest



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 timeline 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 timeline 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:




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:




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 timeline 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 deemphasize 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.

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 }
