Australian (ASX) Stock Market Forum

AmiBroker Tips and Tricks

As a newbie, I look at overall return, DD and as you mentioned CAR/MDD
Got interested in Howard car25 but would lie if i say i worked on it
As time goes i am more and more interested in a way to determine end of life of a system
What i rely on mostly is comparison between BT runs on a set of around 30 specific time periods
Last 10y,year by year or since xx to now, and a dozen or so specific periods:
Crash, down or up periods for asx, going nowhere, edgy time
Then i use gutfeel : mostly better mostly worse..i look at trends of return comparison (i am of the belief that our ecosystems are changing and systems need to be built for current..future time, not focussed on past.)
And i look at overall equity curves: smoothness, return for 2018 calendar year(a time where my initial systems were struggling) , speed of recovery, shape of falls
Very visual and intuitive
Would welcome a more figure based way
 
Is everyone sticking with the old CAR/MDD or does anyone have a particularly good alternative.
@Willzy thanks for joining in with the forum discussions again.

To answer your question I am using the standard metrics and experimenting with alternates but nothing ground breaking.

I have used a combination of snippets like yours above just to get the feel of CBT but I am definitely not using it to for it's full capabilities.
 
Cheers guys!

I also had some limited success, using pearsonsR2 ( a measure of straightness of the equity curve ) the CBT I built had to make sure it treated all trades as the same value ie $10,000 on each trade otherwise compounding would distort the value.

Code:
// User Defined Functions

function pattern1( fn, a, b, d ) // Trapezium based step function where value is between 0.5 and 1.0 (optimal between a and b) if greater than d value = 0.5
{
    y = IIf( fn < a, 1 - ( 0.5 / a ) * ( a - fn ),
             IIf( ( fn >= a AND fn <= b ), 1,
                  IIf( ( fn > b AND fn < d ), 1 - ( 0.5 / b ) * ( fn - b ),
                       0.5 ) ) );
    return y;
}

function ramp( fn, ymin, a, b ) // Ramp function returns a value between ymin and 1 (ramp up between a and b)
{
    y = IIf( fn < a, ymin,
             IIf( ( fn >= a AND fn <= b ), ( ( fn - a ) * ( 1 - ymin ) / ( b - a ) + ymin ),
                  1 ) );
    return y;
}

function step( fn, a ) // Step up function returns 1 if function is greater than or equal to a
{
    y = IIf( fn < a, 0, 1 );
    return y;
}

function between( fn, a, b )
{
    y = IIf( fn >= a AND fn <= b, 1, 0 );
    return y;
}


// --- Initiate Custom Backtest Proceedure
SetCustomBacktestProc( "" );

if( Status( "action" ) == actionPortfolio )
{
    bo = GetBacktesterObject();
 
    bo.backtest();
   
    st = bo.getperformancestats( 0 );
   
    // --- Standard Metrics from Amibroker
    initialEquity = st.GetValue( "InitialCapital" );
    netProfit = st.GetValue( "NetProfit" );
    netProfitPercent = st.getvalue( "NetProfitPercent" );
    totalTrades = st.getvalue( "allqty" );
    car = st.GetValue( "CAR" );
    mean = st.getvalue( "AllAvgProfitLossPercent" );
    A = 0.01 * st.getvalue( "WinnersPercent" );  
    P = st.GetValue( "WinnersAvgProfitPercent" ) / st.GetValue( "LosersAvgLossPercent" ) * -1;
   
    // Calculates Trade Frequency on a Daily Basis
    tradesPerDay = TotalTrades / ( 365.25 * ln( 1 + ( NetProfitPercent / 100 ) ) / ln( 1 + ( CAR / 100 ) ) );
    tradesPerYear = floor(365.25 * tradesPerDay);
   
    // Calculates Expectancy as a Percentage Value
    E = P * A + A - 1;
   
    // Initialize Variables to calculate pearsonR2
    r = 0;
   
    if(tradesPerYear > 5 AND totalTrades >= 5)
    {  
        r = n = x = y = xy = x2 = y2 = sumXY = sumX = sumY = sumX2 = sumY2 = 0;
        for( trade = bo.getfirsttrade(); trade; trade = bo.getnexttrade() )
        {
            profit = trade.getpercentprofit() / 100 * 10000;
            n ++;
           
            y += profit;
            x = n;
           
            sumXY += x*y;
           
            sumX += x;
            sumY += y;
           
            sumX2 += x*x;
            sumY2 += y*y;
        }
       
        nom = n*sumXY - sumX*sumY;
        denom =  sqrt( (n*sumX2 - sumX*sumX) * (n*sumY2 - sumY*sumY) );
       
        r = IIf(denom == 0,0,nom/denom);                              
    }
   
    // Custom Metrics
   

    // --- Objective Function
    ObFn = r;

    // Plot Metrics in Desired Order
    bo.AddCustomMetric( "ObFn", ObFn, Null, Null, 4 );
    bo.AddCustomMetric("Profit $",NetProfit);
    bo.addcustommetric( "A % ", A, Null, Null, 2 );
    bo.addcustommetric( "W/L", P, Null, Null, 2 );
    bo.addcustommetric( "E", E, Null, Null, 2 );
    bo.AddCustomMetric( "#T/Yr", tradesPerYear, Null, Null, 0 );
}

In that snippet ObFn = r = pearsonR2 value
 
Following on from discussions about Rotational trading I have pieced together some code that ranks stocks in your selected watchlist.

I am thinking that you could run in at the end of the month and review your portfolios positions against their current rank as defined by your criteria to get a feel for your stock selections.

Obviously you could incorporate this into your system but pretty easy just to run at end of the month (2nd last day of month)

- Exploration is run against selected watchlist

upload_2020-6-11_10-7-38.png
- Ranks each stock based on ROC(Close, 60) - which can be changed to your preference

upload_2020-6-11_10-8-20.png

- Only displays positive valves of ROC for long only system

- Only displays results if 2nd last day of month as you might want to trade on the last day
Filter = TradeDay;


Code:
// Ranking of stocks in current watchlist

if ( GetOption( "ApplyTo" )== 2 )
{
    wlnum = GetOption( "FilterIncludeWatchlist" );
    List = CategoryGetSymbols( categoryWatchlist,wlnum ) ;
}
else
if ( GetOption( "ApplyTo" )== 0 )
{
    List = CategoryGetSymbols( categoryAll, 0 );
}
else
{
     Error( "Theformula works fine if your ApplyTo setting is 'Filter' or 'All' " );
}


if ( Status("stocknum")== 0 ) //GENERATE RANKING WHEN WE ARE ON VERY FIRST SYMBOL
{
    StaticVarRemove( "values*" );

    for (n = 0; ( Symbol = StrExtract(List, n ) )  != "";  n++    )
    {
        SetForeign (symbol );
        values = ROC(Close, 60); // ROC Indicator used to create set of values for Ranking
        RestorePriceArrays();
        StaticVarSet (  "values"  +  symbol,values );
        _TRACE(symbol );
    }

    StaticVarGenerateRanks( "rank", "values", 0, 1224 );
}

symbol = Name();

LastDayOfMonth = IIf( (Month() == Ref( Month(), 1) AND (Month() != Ref( Month(), 2)) ), 1, 0);
TradeDay = LastDayOfMonth ;

values = StaticVarGet ( "values" +  symbol);
rank = IIf (TradeDay, StaticVarGet ( "rankvalues" +  symbol), Null);

PositionScore = IIf(values < 0, 0, values ); // Long only

SetSortColumns( 4 );
Filter = TradeDay;
   
AddColumn ( PositionScore, "ROC Values" );
AddColumn ( rank, "rank",1);

Enjoy !​
 
Alright I'm back again with an Market Regime Filter - Inspired by Matt Radtke - quantforhire

I have created some framework that can be used / modified as you see fit, but basically the positionscore is weighted depending on the market regime filter.

You could use this to adjust stops, position sizes or ???? yep that's right whatever you can dream up.

Basically we have ;

1. 4 x market regimes defined by combinations of Stock Sector Index and Volatility using the S&P/ASX 200 VIX Index (XVI)
Regimes = VolatileBear, QuietBear, QuietBull & VolatileBull​

2. Position score weighted by regime

3. Standard MA Crossover, ASX200, $10k Fixed Position size, Max 20 Positions, $100k Equity, Long Only

4. results ranked on CAR/MDD

*** For education purposes only *****

No Regime Filter.............................With Regime Filter

upload_2020-6-11_20-46-32.png upload_2020-6-11_20-46-59.png


Code:
// Market Regime Filter

/* NORGATE Data Handling: -------------------------------------------------------*/

#include_once "C:\Users\woods_7878\OneDrive\Formulas\Norgate Data\Norgate Data Functions.afl"
OnSecondLastBarOfDelistedSecurity = !IsNull(GetFnData("DelistingDate")) AND (BarIndex() == (LastValue(BarIndex()) -1) OR DateTime() >= GetFnData("DelistingDate") ) ;
OnLastTwoBarsOfDelistedSecurity = !IsNull(GetFnData("DelistingDate")) AND (BarIndex() >= (LastValue(BarIndex()) -1) OR DateTime() >= GetFnData("DelistingDate") );


/* BACKTEST Parameters:------------------------------------------------------------------*/

SetOption ( "CommissionMode", 2 ); // $ per trade
SetOption ( "CommissionAmount", 30 ); // $ Amount per trade
SetOption ( "InitialEquity", 10000 );
SetOption ( "AccountMargin", 100);
PositionSize = 10000;
SetPositionSize( PositionSize, spsValue );
MaxPos = 20;
SetOption( "MaxOpenPositions", MaxPos );
SetTradeDelays( 1, 1, 1, 1 );
SetOption ( "AllowSameBarExit", 0);
SetOption ( "SeparateLongShortRank", 1);

/* Volatility Filter:------------------------------------------------------------------*/
VIXImported = Foreign("$XVI","C"); // The S&P/ASX 200 VIX Index (XVI) calculates the amount of volatility expected in the market over the next 30 days.
VIXQuiet = MA(VIXImported,5) <= Percentile( MA(VIXImported,5), 252, 35 ); // Current MA(VIX) ranks within Bottom 35% of last 252 days
VIXVolatile = MA(VIXImported,5) > Percentile( MA(VIXImported,5), 252, 35 );

/* PRICE Filter:------------------------------------------------------------------*/
NorgateIndex = NorgateIndustryIndex("$XJO", 1 ,"PR");
SectorIndexImported = Foreign(NorgateIndex,"C"); // Brings in sector index name XEJ, XMJ etc
BullMarket = MA(SectorIndexImported,5) > MA(SectorIndexImported,252); // Defines if in Bull or Bear
BearMarket = MA(SectorIndexImported,5) < MA(SectorIndexImported,252);

VolatileBear = BearMarket AND VIXVolatile;
QuietBear = BearMarket AND VIXQuiet;
QuietBull = BullMarket AND VIXQuiet;
VolatileBull = BullMarket AND VIXVolatile;

//RegimeFilter = IIf( VolatileBear, Optimize("VolatileBear", 1000, 0, 4000, 1000), IIf( QuietBear, Optimize("QuietBear", 3000, 0, 4000, 1000),
 //IIf( QuietBull, Optimize("QuietBull", 0, 0, 4000, 1000), IIf( VolatileBull, Optimize("VolatileBull", 3000, 0, 4000, 1000), 0))));

RegimeFilter = IIf( VolatileBear, 2000, IIf( QuietBear, 3000, IIf( QuietBull, 0, IIf( VolatileBull, 3000, 0)))); // Weighting to PositionScore
 
PositionScore = ROC(Close, 100) + RegimeFilter;

period = 30; // number of averaging periods
m = MA( Close, period ); // simple moving average

_SECTION_BEGIN("Buy / Sell");
{
BuyNorgate = NorgatePaddingStatusTimeSeries()==0 AND NOT OnLastTwoBarsOfDelistedSecurity;
Buy = Cross( Close, m ) AND BuyNorgate;

SellNorgate = OnSecondLastBarOfDelistedSecurity;
Sell = Cross( m, Close ) OR SellNorgate;

Buy = ExRem(Buy,Sell);
Sell = ExRem(Sell,Buy);

Short = Cover = 0;

Short = ExRem(Short,Cover);
Cover = ExRem(Cover,Short);
}

_SECTION_BEGIN("Exploration");
{
if( Status( "Action" ) == actionExplore ); // SetSortColumns( -5 );
Filter = 1;
AddColumn(PositionScore, "Score", 1.2, colorDefault, colorDefault, 70);

AddColumn( VIXImported, "$XVI",1.2,colordefault,colorDefault,50 );
AddtextColumn( NorgateIndex, "Index");
AddColumn( VolatileBear, "Volatile Bear",1,
    IIf( VolatileBear, colorGreen, colorRed),
    IIf( VolatileBear, colorGreen, colorRed), 80);
AddColumn( QuietBear, "Quiet Bear",1,
    IIf( QuietBear, colorGreen, colorRed),
    IIf( QuietBear, colorGreen, colorRed), 80);
AddColumn( VolatileBull, "Volatile Bull",1,
    IIf( VolatileBull, colorGreen, colorRed),
    IIf( VolatileBull, colorGreen, colorRed), 80);
AddColumn( QuietBull, "Quiet Bull",1,
    IIf( QuietBull, colorGreen, colorRed),
    IIf( QuietBull, colorGreen, colorRed), 80);

}

Exploration

upload_2020-6-11_20-49-14.png

Hopefully this is useful to someone and the code will require a few tweaks but does give you some more food for thought.

Happy Trading...​
 
Alright I'm back again with an Market Regime Filter - Inspired by Matt Radtke - quantforhire

I have created some framework that can be used / modified as you see fit, but basically the positionscore is weighted depending on the market regime filter.

You could use this to adjust stops, position sizes or ???? yep that's right whatever you can dream up.

Basically we have ;

1. 4 x market regimes defined by combinations of Stock Sector Index and Volatility using the S&P/ASX 200 VIX Index (XVI)
Regimes = VolatileBear, QuietBear, QuietBull & VolatileBull​

2. Position score weighted by regime

3. Standard MA Crossover, ASX200, $10k Fixed Position size, Max 20 Positions, $100k Equity, Long Only

4. results ranked on CAR/MDD

*** For education purposes only *****

No Regime Filter.............................With Regime Filter

View attachment 104630 View attachment 104631


Code:
// Market Regime Filter

/* NORGATE Data Handling: -------------------------------------------------------*/

#include_once "C:\Users\woods_7878\OneDrive\Formulas\Norgate Data\Norgate Data Functions.afl"
OnSecondLastBarOfDelistedSecurity = !IsNull(GetFnData("DelistingDate")) AND (BarIndex() == (LastValue(BarIndex()) -1) OR DateTime() >= GetFnData("DelistingDate") ) ;
OnLastTwoBarsOfDelistedSecurity = !IsNull(GetFnData("DelistingDate")) AND (BarIndex() >= (LastValue(BarIndex()) -1) OR DateTime() >= GetFnData("DelistingDate") );


/* BACKTEST Parameters:------------------------------------------------------------------*/

SetOption ( "CommissionMode", 2 ); // $ per trade
SetOption ( "CommissionAmount", 30 ); // $ Amount per trade
SetOption ( "InitialEquity", 10000 );
SetOption ( "AccountMargin", 100);
PositionSize = 10000;
SetPositionSize( PositionSize, spsValue );
MaxPos = 20;
SetOption( "MaxOpenPositions", MaxPos );
SetTradeDelays( 1, 1, 1, 1 );
SetOption ( "AllowSameBarExit", 0);
SetOption ( "SeparateLongShortRank", 1);

/* Volatility Filter:------------------------------------------------------------------*/
VIXImported = Foreign("$XVI","C"); // The S&P/ASX 200 VIX Index (XVI) calculates the amount of volatility expected in the market over the next 30 days.
VIXQuiet = MA(VIXImported,5) <= Percentile( MA(VIXImported,5), 252, 35 ); // Current MA(VIX) ranks within Bottom 35% of last 252 days
VIXVolatile = MA(VIXImported,5) > Percentile( MA(VIXImported,5), 252, 35 );

/* PRICE Filter:------------------------------------------------------------------*/
NorgateIndex = NorgateIndustryIndex("$XJO", 1 ,"PR");
SectorIndexImported = Foreign(NorgateIndex,"C"); // Brings in sector index name XEJ, XMJ etc
BullMarket = MA(SectorIndexImported,5) > MA(SectorIndexImported,252); // Defines if in Bull or Bear
BearMarket = MA(SectorIndexImported,5) < MA(SectorIndexImported,252);

VolatileBear = BearMarket AND VIXVolatile;
QuietBear = BearMarket AND VIXQuiet;
QuietBull = BullMarket AND VIXQuiet;
VolatileBull = BullMarket AND VIXVolatile;

//RegimeFilter = IIf( VolatileBear, Optimize("VolatileBear", 1000, 0, 4000, 1000), IIf( QuietBear, Optimize("QuietBear", 3000, 0, 4000, 1000),
 //IIf( QuietBull, Optimize("QuietBull", 0, 0, 4000, 1000), IIf( VolatileBull, Optimize("VolatileBull", 3000, 0, 4000, 1000), 0))));

RegimeFilter = IIf( VolatileBear, 2000, IIf( QuietBear, 3000, IIf( QuietBull, 0, IIf( VolatileBull, 3000, 0)))); // Weighting to PositionScore
 
PositionScore = ROC(Close, 100) + RegimeFilter;

period = 30; // number of averaging periods
m = MA( Close, period ); // simple moving average

_SECTION_BEGIN("Buy / Sell");
{
BuyNorgate = NorgatePaddingStatusTimeSeries()==0 AND NOT OnLastTwoBarsOfDelistedSecurity;
Buy = Cross( Close, m ) AND BuyNorgate;

SellNorgate = OnSecondLastBarOfDelistedSecurity;
Sell = Cross( m, Close ) OR SellNorgate;

Buy = ExRem(Buy,Sell);
Sell = ExRem(Sell,Buy);

Short = Cover = 0;

Short = ExRem(Short,Cover);
Cover = ExRem(Cover,Short);
}

_SECTION_BEGIN("Exploration");
{
if( Status( "Action" ) == actionExplore ); // SetSortColumns( -5 );
Filter = 1;
AddColumn(PositionScore, "Score", 1.2, colorDefault, colorDefault, 70);

AddColumn( VIXImported, "$XVI",1.2,colordefault,colorDefault,50 );
AddtextColumn( NorgateIndex, "Index");
AddColumn( VolatileBear, "Volatile Bear",1,
    IIf( VolatileBear, colorGreen, colorRed),
    IIf( VolatileBear, colorGreen, colorRed), 80);
AddColumn( QuietBear, "Quiet Bear",1,
    IIf( QuietBear, colorGreen, colorRed),
    IIf( QuietBear, colorGreen, colorRed), 80);
AddColumn( VolatileBull, "Volatile Bull",1,
    IIf( VolatileBull, colorGreen, colorRed),
    IIf( VolatileBull, colorGreen, colorRed), 80);
AddColumn( QuietBull, "Quiet Bull",1,
    IIf( QuietBull, colorGreen, colorRed),
    IIf( QuietBull, colorGreen, colorRed), 80);

}

Exploration

View attachment 104632

Hopefully this is useful to someone and the code will require a few tweaks but does give you some more food for thought.

Happy Trading...​
@Trav. , What is the period you used for your with/without backtests? January start so including crash?
Great post btw
 
Alright I'm back again with an Market Regime Filter - Inspired by Matt Radtke - quantforhire

I have created some framework that can be used / modified as you see fit, but basically the positionscore is weighted depending on the market regime filter.

Hi @trav, firstly thanks for sharing this code and also all of your other posts. They are enlightening

However, I have run your code but without success.

I have had to modify your code as follows -

Line 5 changed to :

#include_once "Formulas\Norgate Data\Norgate Data Functions.afl" //delete reference to your drive location

On foreign symbols I have included the suffix “.au” This is for my Norgate setup. [btw, also ran with your code, ie without the .au - however no change]

Other than those changes, my code is as yours. For education, would love to identify the difference


I do not get any trades when I run the back test. The Exploration looks as follows – as a point of reference when you look at A2M your position score is 3021.19, whilst mine is 21.19. The difference is my score doesn’t pick up the RegimeFilter value.

Untitled.png
 
#include_once "Formulas\Norgate Data\Norgate Data Functions.afl" //delete reference to your drive location

@CNHTractor yes good pickup mate, I should have thought about the drive reference, not very professional of me :laugh::laugh::laugh:

And yes unfortunately the data format "xxx.au" is a pain but lets have a look ...

Since the $XVI value looks good, I would look at is the Price filter section and the $XJO date which is the other 2nd part of the filter and you might have to change the $XJO code there as well

upload_2020-6-12_6-16-44.png

I added in the following Sector column to check on the value coming in.

AddColumn ( SectorIndexImported, "Sector", 1.2,colordefault,colorDefault,50 );

upload_2020-6-12_6-22-50.png

You still should generate buys regardless of the filter and I noticed you have the range set to 1 bar in the screen shot so maybe that is also holding you out.

Give it a go and see if we can match up the data.
 
@CNHTractor I just thought that I left in the following bit of code which may cause issues depending on your data provider so remove that and I am sure that will fix the buy issue

Highlighted in yellow

upload_2020-6-12_6-30-50.png
 
And FWIW, with premium data no need for .au
Use $vix for us volatility
And from memory xao wo $ for index...confirm by test
If AB does not find a foreign code, it is replaced by the current code with sometimes interesting outcomes :)
 
@trav, I had already changed line 30 as follows
Code:
NorgateIndex = NorgateIndustryIndex("$XJO.au", 1 ,"PR");

I have changed Buy/Sell as suggested:
Code:
_SECTION_BEGIN("Buy / Sell");
{
//BuyNorgate = NorgatePaddingStatusTimeSeries()==0 AND NOT OnLastTwoBarsOfDelistedSecurity;
Buy = Cross( Close, m );// AND BuyNorgate;

//SellNorgate = OnSecondLastBarOfDelistedSecurity;
Sell = Cross( m, Close ); // OR SellNorgate;

@qldfrog, I am using Norgate data and my index is $XJO.au, etc

@trav, I have also added :
Code:
AddColumn ( SectorIndexImported, "Sector", 1.2,colordefault,colorDefault,50 );

When exploration is run the sector value is blank, as follows:Untitled.png

So possibly there is something in respect of the Sector?

Your code is interesting and I am extremely keen to get it to work. It is the first time I have delved into the Norgate extra data.
 
So possibly there is something in respect of the Sector?

Yes that looks like the problem. Maybe go to a chart and type in the symbol $XSJ or $XUJ etc and this should bring up some information to help see what is going on.

My chart title for $XSJ has the close value @ 12336.3

upload_2020-6-12_7-47-5.png

and from the previous post you can see that this value should be displayed in the column.

upload_2020-6-12_6-22-50-png.104655


Have a look to see what you get?
 
@trav, chart of $XSJ.au as follows. All data looks good.

Untitled.png

When you look at the exploration the Index shows as $XSJ and not $XSJ.au So possibly there is a disconnect here?
 
When you look at the exploration the Index shows as $XSJ and not $XSJ.au So possibly there is a disconnect here?

Yes that is what I am thinking.

You use Premium Data and I am using Norgate Data, so there is a problem somewhere. Maybe email them to get a quick answer or work around for this line

NorgateIndustryIndex("$XJO", 1 ,"PR")

I was just reading the premium data web page and there is a topic about switching to Norgate but again maybe ask them about the pros and cons.

https://www.premiumdata.net/support/NDU-release.php
 
When exploration is run the sector value is blank

@CNHTractor you can try this code, @Trav. code slightly modified for Norgate (NDU)

// Market Regime Filter

/* NORGATE Data Handling: -------------------------------------------------------*/

#include_once "C:Formulas\Norgate Data\Norgate Data Functions.afl"
//OnSecondLastBarOfDelistedSecurity = !IsNull( GetFnData( "DelistingDate" ) ) AND( BarIndex() == ( LastValue( BarIndex() ) - 1 ) OR DateTime() >= GetFnData( "DelistingDate" ) ) ;
//OnLastTwoBarsOfDelistedSecurity = !IsNull( GetFnData( "DelistingDate" ) ) AND( BarIndex() >= ( LastValue( BarIndex() ) - 1 ) OR DateTime() >= GetFnData( "DelistingDate" ) );

/* BACKTEST Parameters:------------------------------------------------------------------*/

SetOption( "CommissionMode", 2 ); // $ per trade
SetOption( "CommissionAmount", 30 ); // $ Amount per trade
SetOption( "InitialEquity", 10000 );
SetOption( "AccountMargin", 100 );
PositionSize = 10000;
SetPositionSize( PositionSize, spsValue );
MaxPos = 20;
SetOption( "MaxOpenPositions", MaxPos );
SetTradeDelays( 1, 1, 1, 1 );
SetOption( "AllowSameBarExit", 0 );
SetOption( "SeparateLongShortRank", 1 );

/* Volatility Filter:------------------------------------------------------------------*/
VIXImported = Foreign( "$XVI.au", "C" ); // The S&P/ASX 200 VIX Index (XVI) calculates the amount of volatility expected in the market over the next 30 days.
VIXQuiet = MA( VIXImported, 5 ) <= Percentile( MA( VIXImported, 5 ), 252, 35 ); // Current MA(VIX) ranks within Bottom 35% of last 252 days
VIXVolatile = MA( VIXImported, 5 ) > Percentile( MA( VIXImported, 5 ), 252, 35 );

/* PRICE Filter:------------------------------------------------------------------*/
NorgateIndex = ParamStr( "Index Code", "$XJO.au" );
SectorIndexImported = Foreign( NorgateIndex, "C" );

//NorgateIndex = Foreign( "$XJO.au");
//SectorIndexImported = Foreign( NorgateIndex, "C" ); // Brings in sector index name XEJ, XMJ etc
BullMarket = MA( SectorIndexImported, 5 ) > MA( SectorIndexImported, 252 ); // Defines if in Bull or Bear
BearMarket = MA( SectorIndexImported, 5 ) < MA( SectorIndexImported, 252 );

VolatileBear = BearMarket AND VIXVolatile;
QuietBear = BearMarket AND VIXQuiet;
QuietBull = BullMarket AND VIXQuiet;
VolatileBull = BullMarket AND VIXVolatile;

//RegimeFilter = IIf( VolatileBear, Optimize("VolatileBear", 1000, 0, 4000, 1000), IIf( QuietBear, Optimize("QuietBear", 3000, 0, 4000, 1000),
//IIf( QuietBull, Optimize("QuietBull", 0, 0, 4000, 1000), IIf( VolatileBull, Optimize("VolatileBull", 3000, 0, 4000, 1000), 0))));

RegimeFilter = IIf( VolatileBear, 2000, IIf( QuietBear, 3000, IIf( QuietBull, 0, IIf( VolatileBull, 3000, 0 ) ) ) ); // Weighting to PositionScore

PositionScore = ROC( Close, 100 ) + RegimeFilter;

period = 30; // number of averaging periods
m = MA( Close, period ); // simple moving average

_SECTION_BEGIN( "Buy / Sell" );
{
// BuyNorgate = NorgatePaddingStatusTimeSeries() == 0 AND NOT OnLastTwoBarsOfDelistedSecurity;
Buy = Cross( Close, m ) ;

// SellNorgate = OnSecondLastBarOfDelistedSecurity;
Sell = Cross( m, Close ) ;

Buy = ExRem( Buy, Sell );
Sell = ExRem( Sell, Buy );

Short = Cover = 0;

Short = ExRem( Short, Cover );
Cover = ExRem( Cover, Short );
}

_SECTION_BEGIN( "Exploration" );
{
if( Status( "Action" ) == actionExplore ); // SetSortColumns( -5 );

Filter = 1;
AddColumn( PositionScore, "Score", 1.2, colorDefault, colorDefault, 70 );

AddColumn( VIXImported, "$XVI", 1.2, colordefault, colorDefault, 50 );
AddtextColumn( NorgateIndex, "Index" );
AddColumn( VolatileBear, "Volatile Bear", 1,
IIf( VolatileBear, colorGreen, colorRed ),
IIf( VolatileBear, colorGreen, colorRed ), 80 );
AddColumn( QuietBear, "Quiet Bear", 1,
IIf( QuietBear, colorGreen, colorRed ),
IIf( QuietBear, colorGreen, colorRed ), 80 );
AddColumn( VolatileBull, "Volatile Bull", 1,
IIf( VolatileBull, colorGreen, colorRed ),
IIf( VolatileBull, colorGreen, colorRed ), 80 );
AddColumn( QuietBull, "Quiet Bull", 1,
IIf( QuietBull, colorGreen, colorRed ),
IIf( QuietBull, colorGreen, colorRed ), 80 );
AddColumn( SectorIndexImported, "Sector", 1.2, colordefault, colorDefault, 80 );

}

Skate.
 
You use Premium Data and I am using Norgate Data, so there is a problem somewhere. Maybe email them to get a quick answer or work around for this line

Hi thanks for that. I was also thinking about emailing Norgate.

btw, I am also using Norgate - so not sure why we are different. But never mind.
 
Last edited:
Top