Australian (ASX) Stock Market Forum

Dump it Here

ive spent the last couple of weeks working and learning amibroker and started with your WTT code. its been a really nice learning process.

Back in the old days
The year was late 2014 or early 2015 @captain black gave me a simple weekly breakout strategy to play around with. The kindness of the Captain got me started in figuring out what was required to trade systematically. Back on the 13th November 2020, I was revisiting old strategies I traded back in my early days. The strategy was the "BlueWren Strategy" & with additional knowledge improvements flowed.

I was looking to trade another strategy
I'm surprised that a simple breakout strategy still works efficiently with today's volatility. The resurrected strategy has been trading for 9 weeks with pleasing results.

The results below are from "live trading" (not backtest results)
The BlueWren Strategy is 20 positions $100k portfolio (bet size $5k)

BlueWren Dashboard Capture.JPG




BlueWren Equity Capture.JPG

It's worth remembering
The kindness of others should never be underestimated.

Skate.
 
KingFisher Logo name.jpg

While I'm reminiscing
I've been back trading my old KingFisher strategy a few weeks now (9 weeks to be precise) & it's travelling as well-as-expected with the recent swings in the markets.

I was curious
At the start of November 2020, I was eager to find out if my old strategies after being "tweaked" would still be as relevant today as yesteryear. To my surprise, they still work. The last two weeks have been extremely kind to all my systems.

The results below are from "live trading" (not backtest results)
The KingFisher Strategy is 20 positions $100k portfolio (bet size $5k).

KingFisher Line Chart.jpg


Skate.
 
IMHO the charts look better on the strategy I programmed on Tradingview.com. But there is not an adequate stock scanner available there.

Before purchasing AmiBroker I was using Stockcharts.com as my stock scanner. Unfortunately they do not allow Russell 3000 as a scan filter.

I am in this trade live.

8wkmWyMF.png
 
@Skate certainly using your WTT as a learning process and not to trade. atleast not in its standard form. I honestly wouldnt have even conisdered diving into making my own mechanical system if it wasnt for this good starting point. Got help from davedagr8 as well which is nice.
Thank you both..

Theres still alot for me to learn.. there is things happening in the exploration vs backtest that i cant explain. Example the entry point of a particular symbol is correct on both the backtest and the exploration. The same symbol exits on exploration via a trailing stop, but stays open and running with a backtest..

@dpong do you want me to run your code on the ASX with historical constituents and do a 20 year backtest?
 
@Skate certainly using your WTT as a learning process and not to trade. atleast not in its standard form. I honestly wouldnt have even conisdered diving into making my own mechanical system if it wasnt for this good starting point. Got help from davedagr8 as well which is nice.
Thank you both..
Theres still alot for me to learn.. there is things happening in the exploration vs backtest that i cant explain. Example the entry point of a particular symbol is correct on both the backtest and the exploration. The same symbol exits on exploration via a trailing stop, but stays open and running with a backtest..

@othmana86, it's difficult getting your head around the differences between an Exploration Analysis versus a Backtest Report. @Lone Wolf gave you the comparisons between a backtest & exploration as they are looking for different things. Explore is looking for signals generated in that period. It will include signals for the following week. Backtest will look for any trades opened during that period. The signals for those backtest trades occurred in the week prior to your window. Or maybe more simply - The backtest results for that period should match the exploration results seen at the end of the previous week.

Refresher
As for your most recent issues, others will most likely explain it more succinctly than I could. In the meantime, I'm suggesting you revisit Lone Wolf's post as sometimes a second read makes things clearer. Also, the post has real examples attached. The post I'm referring to can be found here: https://www.aussiestockforums.com/threads/dump-it-here.34425/post-1104950

Skate.
 
@Skate yeah i referred back to that post. for entry ive got that sorted..its fine they match. i got the dates worked out so a big tick there.
The issue i am having at the moment is the exit, which is why i asked how your exit is done. ill give you an example to help explain what im currently trying to solve..
so on
exploration signal generated to buy VMS on 18/12 for an entry on the 21/12. at 0.05c. tick
backtester also shows signal on the same day. tick

exploration signals an trailing stop exist on 31/12 for an exit the next candle 4/01 at .05c.
backtester keeps it running...does not close the trade. which is the correct way because it did not close -20% from the entry bar.
which begs the question..how can i rely on the exploration signals? so somethings wrong just not sure what yet..
1610083183802.png1610084361034.png



1610084257140.png
 
@Skate the exploration signals an trailing stop exist on 31/12 for an exit the next candle 4/01 at .05c.
backtester keeps it running...does not close the trade. which is the correct way because it did not close -20% from the entry bar.
which begs the question..how can i rely on the exploration signals? so somethings wrong just not sure what yet..
View attachment 117996View attachment 118000



View attachment 117999

@othmana86 I'm assuming you have altered my original code. Please upload the (WTT.afl) that has given you the results in the post above.

Skate.
 
#include_once "Formulas\Norgate Data\Norgate Data Functions.afl"
stockInIndex = NorgateIndexConstituentTimeSeries("$XAO.AU");
stockIn200 = NorgateIndexConstituentTimeSeries("$XJO.AU");
stockIn50 = NorgateIndexConstituentTimeSeries("$XFL.AU");

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") );

_SECTION_BEGIN( "# Skate's WTT Modified Exploration" );
//=================================================================================
//1. The "SetOptions" are management options & they are a feature of Amibroker
//=================================================================================
TradingFunds = Param( "Trading Funds - $", 5000, 1000, 10000000, 1000 ); // User-definable parameter, accessible via Exploration parameters - changes are reflected immediately. (Default $5k bets) - INSERT any amount
InitialEquity= 20000;
SetOption( "InitialEquity", InitialEquity ); // $20k Inital Equity (allows for 20 X $5k bets)
SetOption( "PriceBoundChecking", 1 ); // True: Adjust prices so that they fall within the High-Low range
SetOption( "CommissionMode", 2 ); // Use $ amount
SetOption( "CommissionAmount", 6 ); // CommSec commission rate
SetOption( "UsePrevBarEquityForPosSizing", 1 ); // True: Use previous bar closing equity to perform position sizing
SetOption( "AllowSameBarExit", False ); // False: Trade is exited & we move to next bar ignoring other signals
SetForeign( "$XAO.au", True , True ); // I've used the new Norgate Updater (NDU) format - change if the format is different to your data supplier
RestorePriceArrays( True ); // Restores original price and volume arrays after the call to SetForeign.
SetTradeDelays( 1, 1, 1, 1 ); // Trade delays, the delay is required for backtesting
//=================================================================================
//2. The "Index Filter" - decides when we will trade & also our trailing stop levels
//=================================================================================
Index = Foreign("$XAO.au","C",True);
MAfilter = MA( Index, 10 ); // 10 week lookback period
IndexBuyFilter = Index > MAfilter; // Index Filter = ON: When the close is greater than the 10 week simple moving average the Index Filter is ON [trailing stop set to 20%] + [buy + sell signals generated]
IndexSellFilter = Index < MAfilter; // Index Filter = OFF: When the close is less than the 10 week simple moving average the Index Filter is OFF [shortens trailing stop to 10%] + [only sell signals generated]
RestorePriceArrays( True ); // Restores original arrays after the call to SetForeign.
//=================================================================================
//3. Add all our other filters
//=================================================================================
Liq = C * V; // Liquidity Filter
CV = 2000000; // Volume Filter
Liqfactor = Liq > CV; // Liquidity Filter
ROCFilter = ROC( C, 20 ) > 30; // Rate Of Change (ROC) Momentum filter
ROCParameter = Param( "ROC Parameter", 8, 0, 52, 1 ); // 8 week Rate of Change period
MOMFilter = ( ROC( C, 10 ) >= ROCparameter ); // Momentum filter - the closing price of the last 10 weeks is greater than the last 8 weeks
NoStrength = Close < MA( Close, 12 ); // If the closing price is less then the Simple Moving Average of the last 12 weeks it's considered there is no strength in the move
//=================================================================================
//4. Add a Buy condition
//=================================================================================
Cond1 = C > Ref( HHV( C, 10 ), -1 ); // Buy when the closing price is greater than the highest High Value of the last 20 weeks
Cond2 = IndexBuyFilter; // Buy ONLY when the Index Filter is ON
cond3 = C >= .05; // Buy only if the closing price is greater $0.05 (5 cents)
cond4 = C <= 10000; // Buy only if the closing price is less than $10.00
cond5 = liqfactor; // Buy only when the Liquidity filter is TRUE
cond6 = ROCFilter AND MOMFilter; // Buy only when the Rate of Change filter & Momentum filter is TRUE

Buy = cond1
AND cond2
AND cond3
AND cond4
AND cond5
AND cond6
AND NOT OnLastTwoBarsOfDelistedSecurity
// AND stockinindex
;
//=================================================================================
//5. Add a sell condition
//=================================================================================
Sell = C < MA( C, 30 ) AND NoStrength; // Sell when the close is less than the moving average of the last 50 weeks with the closing price is less than the Simple Moving Average of the last 12 weeks
Sell = Sell OR OnLastTwoBarsOfDelistedSecurity;
//=================================================================================
//6. Add a two-stage trailing stop
//=================================================================================

ts1 = 20;
ts2 = 8;
ts = IIf( Indexbuyfilter , ts1 , ts2 );
ApplyStop( stopTypeTrailing , stopModePercent , ts , exitatstop = 2 ); // Apply Stop = [ts] Trailing Stop [exitatstop = 2] means check High-Low prices but exit NEXT BAR on regular trade price.
//=================================================================================
//7. Add "Position Sizing"
//=================================================================================
BuyPrice = Open; // Buy the next day at open
SellPrice = Open; // Sell the next day at open

Buy = ExRem( Buy, Sell ); // Removes additional buy signals
Sell = ExRem( Sell, Buy ); // Removes additional sell signals

PosQty = 20; // Position Quantity = Maximum 20 positions
PositionSize = -100 / posqty; // 100% of the equity divided by the Position Size
SetOption( "MaxOpenPositions", PosQty ); // Maximum number of open position
//=================================================================================
//8. Add "Filters for the Exploration Analysis"
//=================================================================================
//Filter = Buy OR Sell; // Buy & Sell Filters
//=================================================================================
//9. Add Buy & Sell coding for use in trading the pre-auction
//=================================================================================
BuyOffered = Close * 1.00; // +3% Buy premium over the last closing price
BuyOffer = floor( BuyOffered * 100 ) / 100; // The amount is rounded up no matter the price (ceil function used)

SellOffered = Close * 1.00; // -3% Sell premium below the last closing price
SellOffer = floor( SellOffered * 100 ) / 100; // The amount is rounded down no matter the price (floor function used)
//=================================================================================
//10. Add the Exploration code
//=================================================================================
ToBuyPosSize = floor( TradingFunds / BuyOffer ); // Trading Funds divided by buy offer of (+3%) buy premium over the last closing price
ToBuyPosCost = BuyOffer * ToBuyPosSize; // The cost of buying the amount of share
PositionScorer = 100 - Close; // Lowest priced security at BuySetup trigger is taken first
PositionScore = Ref( PositionScorer, -1 ); // Previous bar (-1 bar)

s1 = Sell; // s1 are the original sell signals

if( Status("action") == actionExplore )
{
SetTradeDelays(0,0,0,0);
PositionScore = Positionscorer;
Equity( 2 );
SetSortColumns( 3,-4);
}

Filter = Filter = Status("LastBarInRange") AND (Buy OR Sell); // Buy & Sell Filters


ts = 0; // text selector ....
ts = IIf(Buy,1,0); // Buy signal
ts = IIf(s1,2,ts); // Sell signal
ts = IIf(Sell AND NOT s1,3,ts); // Stop signal

tl = "\nBuy\nSell\nStop"; // String array.

//addmultiTextColumn (ts,tl,"Action",1.2,colorWhite,IIf(Buy,colorDarkGreen,IIf(s1,colorRed,colorOrange)),60);

/***************** HIDE COLUMNS FOR VISUAL ***************/
AddColumn(IIf( Buy, BuyOffer, Null ),"Buy",1.2,colorWhite,IIf(Buy,colorDarkGreen,colorWhite),60);
AddColumn(IIf( Sell, SellOffer, Null),"Sell",1.2,colorWhite,IIf(S1,colorRed,colorWhite),60);
AddColumn(IIf(Sell and NOT s1,SellOffer,0),"Stop",1.2,colorWhite,IIf(Sell AND NOT s1,colorOrange,colorWhite),60);
AddColumn(PositionScorer,"Score");

//AddTextColumn("WTT","Strategy");
//AddTextColumn("ASX","Universe");
//AddTextColumn("MOO","Order Type");
//AddColumn(0,"Buy Stop",1.4); // No buy stop
//AddColumn(0,"Buy LMT"); // no limit
//AddColumn(0,"Sell LMT"); // no limit

AddColumn(-positionSize,"Position Size %");
AddColumn(-positionsize*InitialEquity/100/C,"# Shares");
AddColumn(ts,"ts"); //
//SetSortColumns( 2, -3, -4, -5, -6, 1 ); // Sort the columns in correct order
_SECTION_END();


//=================================================================================
//12. Add code to the chart & plots the signals. Also adding an Index Ribbon
//=================================================================================
_SECTION_BEGIN( "Price" );


SetChartOptions( 0, chartShowArrows | chartShowDates );
_N( Title = StrFormat( "{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) Vol " + WriteVal( V, 1.0 ) + " {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ) ); // Chart settings

Plot( C, "Close", ParamColor( "Color", colorBlack ),
ParamStyle( "Style", styleNoTitle | styleBar, maskAll ) ); // User-definable parameter, accessible via Chart parameters - changes are reflected immediatelly. (Bar Chart Default)

PlotShapes( Buy*shapehollowUpArrow, colorWhite, 0, Low, -20 ); // Displays Buy up arrow on the signal bar
PlotShapes( ( Sell > 0 ) * shapeDownArrow, Coloryellow, 0, High, -40 ); // Displays Sell down arrow on the signal bar
PlotShapes( Ref( Buy, -1 ) * shapeHollowSquare, colorWhite, 0, O, 0, 0 ); // Displays a white square on the buy bar
PlotShapes( Ref( Sell, -1 ) * shapeHollowCircle, colorYellow, 0, O, 0, 0 ); // Displays a yellow circle on the sell bar
PlotShapes(Buy*shapeUpArrow,colorGreen,0,Low);
PlotShapes(Sell*shapeDownArrow,colorRed,0,High);

Indexfilter = IIf( IndexBuyfilter, True, False ); // If Index Filter is TRUE (ON), or If Index Filter is FALSE (OFF),
RibbonColor = IIf( Indexfilter, colorGreen, colorRed ); // If Index Filter is TRUE (ON) the ribbon is GREEN, or If Index Filter is FALSE (OFF) the ribbon is Red
Plot( 1, "", RibbonColor, styleArea | styleOwnScale | styleNoLabel, -0.0001, 190 ); // Plots Index Filter Ribbon [green = ON] [Red = OFF]

for( i = 1; i < BarCount; i++ )
{
if( Buy[i - 1] ) PlotText( "Buy\n@ " + O, i, L * 0.9, colorWhite ); // Displays white buy price (opening price) under the white box (buy bar)

if( sell[i - 1] ) PlotText( "Sell\n@ " + o[ i ], i, H[ i ] * 1.1, colorYellow ); // Displays yellow sell price (opening price) above the yellow circle (sell bar)

}
_SECTION_END();
//=================================================================================
//Bonus Section - Additional Metrics - Win/Loss ratio
//=================================================================================
_SECTION_BEGIN( "Win/Loss Ratio" );
// BONUS - Additional Metrics - Win/Loss ratio for the previous years and includes the number of trades per year
procedure vgWinLossPerYear( YrWin, YrLoss, Yrcnt, trade, mode )
{
dt = IIf( mode == 1, trade.ExitDateTime, trade.EntryDateTime );
n = floor( DateTimeConvert( 8, dt ) );

if( trade.GetProfit() >= 0 ) // profit only
VarSet( YrWin + n, Nz( VarGet( YrWin + n ) ) + 1 );
else // loss only
VarSet( YrLoss + n, Nz( VarGet( YrLoss + n ) ) + 1 );

// cnt all per year
VarSet( Yrcnt + n, Nz( VarGet( Yrcnt + n ) ) + 1 );
}

SetCustomBacktestProc( "" );

if( Status( "action" ) == actionPortfolio )
{
bo = GetBacktesterObject();
bo.Backtest();

yr = Year();
fbr = Status( "FirstBarInRange" );
lbr = Status( "LastBarInRange" );
first_yr = LastValue( ValueWhen( fbr, yr ) );
last_yr = LastValue( ValueWhen( lbr, yr ) );

// iterate closes trades
for( trade = bo.GetFirstTrade(); trade; trade = bo.GetNextTrade() )
vgWinLossPerYear( "YrWin", "YrLoss", "Yrcnt", trade, 0 );

// iterate open trades
for( trade = bo.GetFirstOpenPos(); trade; trade = bo.GetNextOpenPos() )
vgWinLossPerYear( "YrWin", "YrLoss", "Yrcnt", trade, 0 );

// Output per year stats to report file
for( i = first_yr; i <= last_yr; i++ )
{
YrCnt = VarGet( "Yrcnt" + i );
bo.AddCustomMetric( StrFormat( "Year%g (%g trades): WinRatio %1.2f%%, LossRatio %1.2f%%",
i, YrCnt, VarGet( "YrWin" + i ) / YrCnt * 100, VarGet( "YrLoss" + i ) / YrCnt * 100 ) );
}
}

_SECTION_END();
 
exploration signals an trailing stop exist on 31/12 for an exit the next candle 4/01 at .05c.
backtester keeps it running...does not close the trade. which is the correct way because it did not close -20% from the entry bar.
which begs the question..how can i rely on the exploration signals? so somethings wrong just not sure what yet..
I haven't read the whole exchange but you have 2 different set trade delays which is causing your problem ( what I can see )

SetTradeDelays( 1, 1, 1, 1 ); // Trade delays, the delay is required for backtesting

if( Status("action") == actionExplore )
{
SetTradeDelays(0,0,0,0);
PositionScore = Positionscorer;
Equity( 2 );
SetSortColumns( 3,-4);
}
 
Since we are all sharing many systems (covering all the animals in Noah’s ark), I thought I would share one of my own (very simple, yet very profitable). Back-tests have been performed over the same "statistically significant" period as all the other systems presented in this thread (by others). I know back-testing means “jack”, but here are the details and results:

Name.png

Trading Period = 01/01/2020 to 07/01/2021
Initial Trading Capital = $100,000
Number of Positions = 50
Index Filter = None
Universe = Any ASX Ordinary Stock (including delisted)
Shorting = No

A single run of the strategy results in the following:

Single_Run_A.PNG
Single_Run_B.PNG

A Monte-Carlo simulation (2000 run) of the strategy results in the following:

Scatter.PNG

Profit Stats
Maximum Profit: $187,526.46 (187.53%)
Average Profit: $75,675.56 (75.68%)
Minimum Profit: $9,794.98 (9.79%)
Standard Deviation: $26,124.02 (26.12%)
Probability of Profit: 100.00%
Probability of Loss: 0.00%

Percent Winning Trade Stats
Maximum percentage of winning trades: 53.44%
Average percentage of winning trades: 48.26%
Minimum percentage of winning trades: 44.03%
Standard Deviation: 1.38%

Percent Losing Trade Stats
Maximum percentage of losing trades: 55.97%
Average percentage of losing Trades: 51.74%
Minimum percentage of losing trades: 46.56%
Standard Deviation: 1.38%

Maximum Peak-to-Valley Percent Drawdown Stats
Maximum Absolute Percent Drawdown: 40.4258%
Average Absolute Percent Drawdown: 29.8859%
Minimum Absolute Percent Drawdown: 15.5345%
Standard Deviation: 3.5881%

The code (Metastock + Tradesim) for this strategy is as follows:

Entry = (Ref(ExtFml("TradeSim.Rand"),-1) <= 0.05)
{If yesterday’s randomly generated number is less than or equal to 0.05, then BUY}

Exit = (Ref(ExtFml("TradeSim.Rand"),-1) >= 0.9)
{If yesterday’s randomly generated number is greater than or equal to 0.9, then SELL}

Off coarse the results could be improved by adding an index filter.
 
Here is one way that I visualize my trades. It is a histogram chart, done in Excel, and is generated directly from my trading journal. There are currently 20 open trades and 41 closed trades for a total of 61. These are my results from running WTT live since about 1 Jan 2020.

The simulated "bell curve" represents what a normal distribution might look like. I manually put the left side of the "bell curve" just to the left of my biggest single loss, which is $1,200 on this chart. Then I place the right side of the bell curve just past +$1,200 so it is symmetrical. We are looking for a positive edge, so we are most interested in trades that fall outside the normal distribution. Currently I have 12 trades outside of the bell curve. This is also known as a "fat tail." It is exactly what you want.

[Each trade is placed in a bin according to it's gain or loss, and the number of trades in each bin are summed.]

[Amibroker generates a similar chart during backtesting.]

Window_and_2020_Positions-7.jpg
 
Good pickup.

I think Trav is on the right track here.

Applystop is supposed to work from High to Low values, not the close ( i think ). I have always run looping stops so it's never been an issue.

If you add these 2 lines to your code it might give you a clearer picture

AddColumn(HHV(H,BarsSince(Buy)),"Stop check BT",1.4,colorWhite,IIf(LLV(L,BarsSince(Buy))<HHV(H,BarsSince(Buy))*.8,colorRed,colorDarkGreen));
AddColumn(HHV(H,BarsSince(Ref(Buy,1))),"Stop check EX",1.4,colorWhite,IIf(LLV(L,BarsSince(Ref(Buy,1)))<HHV(H,BarsSince(Ref(Buy,1)))*.8,colorRed,colorDarkGreen));

This is more a debugging type line to see if there is a pattern of errors.

1610112849586.png

So thinking about it this is what is really going on under the hood. Green is NOT stopped out, so the backtester wouldn't ( didn't) have stopped out, but the explorer did for VMS due to the different tradedelays. It looks like the issue has come from the first bar. The explorer used the value of .067 and Backtester .063.

Sorry to lead you astray, i don't use applystop and i thought that would work. My Bad

I'll have a think about this more tomorrow.
 
Top