# Trading strategy development - Lessons Learnt



## Harro26 (2 February 2010)

Hi all,

     I've been developing my trading strategy for the past 6 months or so and have finally come up with a system I have the confidence in to trade. I found this site invaluable in developing my stategy and as such I am posting my lessons learnt to give something back.
I caveat all of these with the fact that I have only been trading this system since 1/1/2010 (I'm only up 1.5% since than) so in no way is it proven, the backtest results are good and I believe I have overcome alot of the traps of backtesting/optimization.
My strategy is a trend trading strategy (Long only at this time), I won't give away the exact system but I will give you the high points. My software of choice is Amibroker (With data from premium data) so the code I quote is for this. I also have Stock Doctor but don't realy use this in this strategy (I use it to trade fundamentally good stocks on support and resistance when the market is moving back and forth as it is now)
So here they are, in no particular order:
1. Position size - You want to be trading about 10 stocks at a time. PositionSize = -10; 
A trend trading strategy will not neccessarily give you a greater than 50% win/loss ratio (Mine gives about 40-45%) so the idea of trend trading is to let your wins go and cut your losses short, 10 stocks allows you to do this.

2. Position score - Set this to random 
Positionscore=random(); 
For those not familiar with Amibroker this makes it enter trades randomly, i.e. if on a given day you have enough funds to enter 2 trades but you get 5 buy signals it will choose these at random (If it is not set to random it enters them alphabetically). Each time you hit backtest you will get a different result. This is very important, you may have a system that 1 in 100 times gives you awesome results and the rest of the time tanks. If position score is not set to random and you don't do a few tests (3 is generally considered a good initial sample size) you may only get the good results.
Monte Carlo backtesting is obviously taking this to the next level. You can set up pseudo monte carlo backtesting in Amibroker using the following
PS = Optimize("PS",1,1,100);
Positionscore=random()*PS;
Now instead of hitting backtest hit Optimize, this will give you the results for 100 trades.
3. Trade delays - *It is crucial to get this right. *. I do intraday trading so I get my signals at night and enter buy/sell signals the next day. If doing Intraday trading set your trade delays as follows:
SetTradeDelays(1,1,1,1);
An simple example of setting these incorrectly is as follows:
Buy = Close>open;
Sell = Close>open;
If you trade this with no trade delays you will get amazing results but obviously this is unrealistic.

4. Don't let your backtest results be biased by suvivorism/indexes - The best way to do this is to backtest historical share/index data including delisted stocks, I haven't been able to obtain historical index data (ASX 200 etc.) So I only backtest all Fully paid ordinary shares and delisted stocks. The bottom line is don't backtest the current day ASX200 as this will bias your results (Obviously stocks have done well in the past to get into thew ASX 200). 

5. Trade with the market - Let the market drive your trades (Long/Short how much money to have in at a time etc.). Nobody knows where the market is heading, for every so called expert telling you the market is about to go gangbusters there is one telling you it is about to tank. Your neighbour, relative or best friend definately does not know where the market is heading so don't listen to them either. A simple way of doing this is a moving average following the index you are trading, to do this in Amibroker use the following setup:
XAO = Foreign("XAO","CLOSE");
Now when you use MA(XAO,5)etc. it will look at the all ords.

6. Ensure the stock has enough volume for you to enter - Again this will bias your results, if you try to buy $50000 of a stock that only had $10000 of volume traded you will have to pay a premium for this. Ensure the stock has 5-10 times the average volume traded that you are looking to buy. Use the recent moving average of volume for this, for example if we are buying $10000 per trade set it as follows:

(MA(Volume,10)*Close)>100000

Also, in the setting window under the portfolio tab set limit trade size as a % of entry volume to 10.

7. Basic Trend trading strategy - This can be a number of things, trading off moving averages, hitting fresh highs/lows etc. Come up with something sensible, backtest it, if it makes you some money look at how it could make you more by examining the trades it makes. If it is giving you a bunch of signals look at how to narrow these down to mostly the good ones. 

So far.... The setting for my system are as follows:

PositionSize = -10;
PS = Optimize("PS",1,1,1,10);
PositionScore = Random()*PS;
SetTradeDelays(1,1,1,1);
XAO = Foreign("XAO","CLOSE");

An overview of the system is as follows:

Buy = MA(XAO,15) > MA(XAO,40) // This keeps us trading with the market and will keep us out of the bear markets.
AND (MA(Volume,10)*Close)>100000 // This ensures there is sufficient volume
[Insert trend strategy here]

Sell = [Insert trnd strategy here] // Sell can be alot simpler than buy as you want to get out of a trade as soon as the market moves against you.

By now you should be getting reasonable results, but we can now make them better using volume:

8. Use volume in your entry - Volume drastically improved my results, you want to be buying on increased volume this shows that there is increased interest in  the stock, set this as follows using the medium term moving average:

Volume > (3*MA(Volume,150)) // Volume must be 3 x greater than average

Our strategy now looks like this:

PositionSize = -10;
PS = Optimize("PS",1,1,1,10);
PositionScore = Random()*PS;
SetTradeDelays(1,1,1,1);
XAO = Foreign("XAO","CLOSE");

Buy = MA(XAO,15) > MA(XAO,40) // This keeps us trading with the market
AND (MA(Volume,10)*Close)>100000 // This ensures there is sufficient volume
AND Volume > (3*MA(Volume,150)) // Volume must be 3 x greater than average
[Insert trend strategy here]

Sell = [Insert trnd strategy here] // Sell can be alot simpler than buy as you want to get out of a trade as soon as the market moves against you.

9. Optimization - It is easy to over optimize a system. Optimization is a good thing as you have to set your paramaters to something. To prevent over optimization ensure that the value for your buy/sell paramaters can be changed to sensible values and it will still outperform the market. If your system only works with a specific set of numbers it is probably over optimized.
Also ensure that the system works in a variety of different market conditionss. Finally, to ensure your system is not over optimized........

10. Backtest against foreign markets - I forked out for the US data also for this purpose. Ensure your stategy outperforms in these markets also.

There is 10 of the lessons i've learnt whilst developing my strategy, there is a thousand more, but I'm sick of typing. 
Finally, to give those new to strategy development something to aim for, the average backtested results for my system are as follows:

Testing all ASX fully paid ordinary shares since 2000:
Profit - 600% (Compared with the XAO's 47% rise), outperforms 100% of the time

Testing the NYSE since 1985:
Profit - 1400% (Compared to NYSE composite index's 594% rise), Outperforms 100% of the time (Limited sample size though)

Testing the NASDAQ since 1985:
Profit - 1500% (Compared to NASDAQ composite index's 780% rise),
Outperforms 100% of the time (Again limited sample size)


Good luck.


----------



## Wysiwyg (3 February 2010)

As Howard Bandy has noted many times. It is the out-of-sample test data that should be used to decide on whether to go live or not.

To add to your contribution ... I use this filter to leave the 20c ( change to preference) and below stocks out.   

PriceMin = Param("Price Min",0,0.2000,100,1);
P1 = C > PriceMin;

Also Howard Bandy's brief overview of building a trading system Power Point presentation. 

Bandy -- How to Build an Effective Trading System.ppt


----------



## brty (3 February 2010)

All those lovely numbers and parameters, yet there seems to be a couple of minor ones missing..

1 Bid ask spread
2 Slippage
3 Commissions

brty


----------



## howardbandy (3 February 2010)

Greetings all --

This topic of using random trade selection keeps coming up, and I think it is seriously dangerous.  Please permit me a short rant.

So I ask myself --

If I get up in the morning, run my systems, see that I have signals to buy ten issues and money enough to buy five of them, would I really roll the dice to decide which five?  I would not.  Never.

If you would, then continue on using PositionScore = random();  

If not, then include the criteria to be used to break those ties into either your objective function or PositionScore and design a system that knows how much is available for new positions and lists just those signals that are the best use of those funds.  Every time that system is run, the list will be the same.  If, for some reason, you prefer a different choice, then change the algorithm so the choice you prefer is the one your system lists for you.

Why would I go to the trouble of developing a trading system including all the details of objective function, issue selection, order type, logic, parameters, slippage, commission, taxes, money management, risk analysis, position sizing, in-sample, out-of-sample, walk forward, statistical validation, and all the other things involved -- and then allow my trade selection to be random?  I might just as well paste the stock page of the newspaper on the wall and throw darts.  

I have yet, in nearly fifty years in this business, to meet a successful trader -- individual or trading company -- who uses Random as their trading system.  But your experience may be different.

Thanks for listening,
Howard


----------



## Harro26 (3 February 2010)

howardbandy said:


> Greetings all --
> 
> This topic of using random trade selection keeps coming up, and I think it is seriously dangerous.  Please permit me a short rant.
> 
> ...




Thanks Howard, that's some useful info. 

I use my mechanical trading system to generate potential trades, if there is more trades available than I can enter I look at the fundamentals of the stock to determine which one to enter. This cannot be backtested so setting my positionscore to random gives me my spread of potential profit/loss. I.e. If I completeley mess up my stock selection how much money will I make, If I nail it how much money will I make and on average how much will I make.
You make an interesting point though, I have not looked at using technical indicators to determine my position score. This would obviously have the advantage of eliminating all discretion from the system and my strategy would than be 100% backtested, I'll look into it in further detail.


----------



## Superboot (3 February 2010)

Thanks Harro!

I am currently wading through aminbroker code examples to construct my own system. You have kindly provide many of the concepts I am keen to use in a step by step approach (and in amibroker!). This we give me a real boost in the progression of my system development. Many thanks


----------



## howardbandy (4 February 2010)

Greetings --

There are many things to consider when attempting to combine fundamental analysis with technical analysis.  I have written a paper on that topic.  You can download it from this page:  
http://www.quantitativetradingsystems.com/activities.html
It is the second entry, entitled "Use of Fundamental Data in Active Investing".  

Since that paper was written, Norgate Premium Data has begun distributing the eight digit GICS codes that I refer to on page 23.

Thanks,
Howard


----------



## Harro26 (4 February 2010)

Thanks Howard I'll give it a read.

I've been doing some more thinking regarding positionscore and have a theory that I would be interested in hearing peoples opinion on (Especially yours Howard). 
I absolutely agree that you should not select your positions at random based on a couple of simple signals, you need to decide which of these signals has the highest probability of success based on something (Be it technical or fundamental indicators). My theory, however, is that positionscore should be the last piece of the puzzle when developing a trading strategy.
What I mean is, I believe setting your positionscore to random is a good thing for your initial strategy development. If you can develop a strategy that consistently outperforms the market you are trading, and others, with positionscore set to random than you should in theory have a robust system that is not over optimised.
You than use position score to fine tune your system prior to trading it.
Using positionscore from the get go does not give you this flexibility and could lead to over optimisation, I.e. The combination of your trading strategy and position score could lead to a few good trades by pure chance that inflate your results.

That's my 2c on PositionScore.

Harro


----------



## howardbandy (5 February 2010)

Hi Harro --

PositionScore is a component of the objective function.  

In my opinion, determination of the objective function is the first step in trading system design.

Thanks,
Howard


----------



## Wysiwyg (24 April 2010)

howardbandy said:


> Hi Harro --
> 
> PositionScore is a component of the objective function.
> 
> ...



Hello and thanks for your previous thoughts.

I have a question regarding why position score "random" has better results than position score with criteria. In other words, what happens to make the random selection show better results in testing, please? Can this random selection method be formulated?

This is the process .... "Internally Random() function uses Microsoft C runtime library rand() function scaled to cover 0..1 range" .....


----------



## weird (25 April 2010)

I have a lot of respect towards Bandy, but do disagree with him in some aspects of system development.

I do recommend his books for learning Amibroker, but not for learning how to trade.

Not a fan a using positionscore to have a single path outcome (perhaps if you have limited yourself to a single path then out of sample is important), and am a supporter of using positionscore set to random. 

On a use of this, is for systems which have an entry intraday (not open)  where you do not know the order of trades being filled.

Bandy has provided useful books, which have useful examples of coding in AB, but I know of another critical commenter, such as Jose, which criticizes the use of using the close to enter a trade.

I would take Bandy for what he has to offer, but seriously question and test it.


----------



## SmellyTerror (27 April 2010)

> I might just as well paste the stock page of the newspaper on the wall and throw darts.




That gives me an idea for an iPhone app...


----------



## Wysiwyg (19 May 2010)

Harro26 said:


> Hi all,
> 
> I've been developing my trading strategy for the past 6 months or so and have finally come up with a system I have the confidence in to trade. I found this site invaluable in developing my stategy and as such I am posting my lessons learnt to give something back.
> I caveat all of these with the fact that I have only been trading this system since 1/1/2010 (I'm only up 1.5% since than) so in no way is it proven, the backtest results are good and I believe I have overcome alot of the traps of backtesting/optimization.





> Testing all ASX fully paid ordinary shares since 2000:
> Profit - 600% (Compared with the XAO's 47% rise), outperforms 100% of the time



How is it going Harro. Although limited in AFL experience I have been testing various strategies from year 2000 and I thought your long only trading results are unrealistic due to the limp market conditions from 2000 to 2003 and the global market declines from 2007 to 2009 in which few stocks escaped. This would mean a large chunk of time "out" of the market. How is your strategy going since 1/1/2010? 



> My strategy is a trend trading strategy (Long only at this time), I won't give away the exact system but I will give you the high points. My software of choice is Amibroker (With data from premium data) so the code I quote is for this.



 I also have been working over various trend trading strategies and one thing that is evident with your 15/40 MA is the lag. That is the market has tanked well before the MA15 swings below the MA 40 which signifies not to open long positions. Additionally there are many times when the cross below is brief yet the market had declined to most of its extreme before this. That means long trades are still being opened on the decline due to the lag. 
In my testing, that index filter will not produce above average results. 

Have you considered using the Correlation function? I had improved results using position score with it. Though I know what correlation means, the explanation in AMI.'s Help suggests correlation between two arrays. That being the Index Close and the Stock Close for the period of 20. 


```
Index  = Foreign("^AORD", "C", True); 
PositionScore = Correlation(Index, C, 20);
```
Note that the correlation may be declining also and that is why I implemented a LinRegSlope ...

```
Index  = Foreign("^AORD", "C", True);
Slope = LinRegSlope(Index, 40) > 0;
```
Index advancing and stock correlation worth investing time on I think.


> PositionSize = -10;
> A trend trading strategy will not neccessarily give you a greater than 50% win/loss ratio (Mine gives about 40-45%) so the idea of trend trading is to let your wins go and cut your losses short, 10 stocks allows you to do this.



Again here if one is in a long position then that is capital effectively out of the system until closed and (hopefully) after a while at a large profit. It is only through these infrequent outliers that a 40 - 45% ratio makes the strategy worth pursuing.  Noting that 40 to 60% win/loss, loss/win is the typical range. 


> 2. Position score - Set this to random
> Positionscore=random();
> For those not familiar with Amibroker this makes it enter trades randomly, i.e. if on a given day you have enough funds to enter 2 trades but you get 5 buy signals it will choose these at random (If it is not set to random it enters them alphabetically). Each time you hit backtest you will get a different result.



I agree with Howard that ranking the group with a higher order. Otherwise when it comes to the real thing we don't know which are the best statistical choices. Would you run the 5 stock selections through the psuedo Monte Carlo optimiser to see which one drew the highest results or maybe you use a discretionary fundamental approach in present day testing. 


> 3. Trade delays - *It is crucial to get this right. *. I do intraday trading so I get my signals at night and enter buy/sell signals the next day. If doing Intraday trading set your trade delays as follows:
> SetTradeDelays(1,1,1,1);
> An simple example of setting these incorrectly is as follows:
> Buy = Close>open;
> ...



A trap for absolute beginner EOD strategy developers.


> 4. Don't let your backtest results be biased by suvivorism/indexes - The best way to do this is to backtest historical share/index data including delisted stocks, I haven't been able to obtain historical index data (ASX 200 etc.) So I only backtest all Fully paid ordinary shares and delisted stocks. The bottom line is don't backtest the current day ASX200 as this will bias your results (Obviously stocks have done well in the past to get into thew ASX 200).



Excellent point, excellent. One of the reasons why real time results don't reflect tested results. No two events are replicated and adjusted data smooths out real time stock gyrations. 


> 5. Trade with the market - Let the market drive your trades (Long/Short how much money to have in at a time etc.). Nobody knows where the market is heading, for every so called expert telling you the market is about to go gangbusters there is one telling you it is about to tank.



 When carried out to the letter then when to get in and when to get out "should" be mechanical. One thing I have trouble with is overriding the tested rules. Optimistic and pessimistic  need not be involved but they are forever gnawing away.  


> 6. Ensure the stock has enough volume for you to enter - Again this will bias your results, if you try to buy $50000 of a stock that only had $10000 of volume traded you will have to pay a premium for this. Ensure the stock has 5-10 times the average volume traded that you are looking to buy. Use the recent moving average of volume for this, for example if we are buying $10000 per trade set it as follows:



Easy to cheat on back testing with this one. As I mentioned elsewhere we are buying a piece of the whole days traded volume which will differ significantly at market and trade open in the morning.


> 9. Optimization - It is easy to over optimize a system. Optimization is a good thing as you have to set your paramaters to something. To prevent over optimization ensure that the value for your buy/sell paramaters can be changed to sensible values and it will still outperform the market. If your system only works with a specific set of numbers it is probably over optimized.



You have to admit though that those smooth rising equity curves are easier on the eye than the jagged goat trodden hills. 


> 10. Backtest against foreign markets - I forked out for the US data also for this purpose. Ensure your strategy outperforms in these markets also.



And quite a difference that makes. The S&P 500 has predominantly higher dollar per share stocks than the Oz market. This factor alone produces radically different results. 

Thanks for the read. Back to chasing my tail again now. :


----------



## Superboot (20 May 2010)

Wysiwyg said:


> I also have been working over various trend trading strategies and one thing that is evident with your 15/40 MA is the lag. That is the market has tanked well before the MA15 swings below the MA 40 which signifies not to open long positions. Additionally there are many times when the cross below is brief yet the market had declined to most of its extreme before this. That means long trades are still being opened on the decline due to the lag.
> In my testing, that index filter will not produce above average results.




Hiya Wysiwyg,

From one of Harro's earlier posts, I tested using the XAO as a filter to stay in/out of the market and it has significantly improved my backtest results. Initially I only had it in the buy condition i.e. not further buys but would hold open any that were active. I then added this to the sell condition as well and it improved the results even further. I guess the sucess/failure of an indicator filter such as the all ords, is also dependant on the system you have developed.

My 

Cheers


----------



## Wysiwyg (20 May 2010)

Superboot said:


> Hiya Wysiwyg,
> 
> From one of Harro's earlier posts, I tested using the XAO as a filter to stay in/out of the market and it has significantly improved my backtest results. Initially I only had it in the buy condition i.e. *not further buys* but would hold open any that were active.
> My
> ...






> Buy = MA(XAO,15) > MA(XAO,40) // *This keeps us trading with the* *market*



 Bollocks. 

Hello SB, In reference to the bold print, a strategy using the MA15 > MA40 is shown on this chart. The market had dropped more than 300 points on these two examples (by no means the worst) before the stop buying rule begins. That means still buying on the way down right up to the cross over. That means buying and being stopped out or holding with a significant loss. MA crosses are extremely lagging. If your "back test" improved with it then all the best.

W.


----------



## Superboot (20 May 2010)

Hey Wysiwyg,

Can I pose a question - if you didn't have an index filter and stayed in a falling market would you be better/worse off? 

I would argue you could potentially still get buys signals in a falling market, which are likely to have a lower probability of success compared to a rising market.

I hear what you are saying about the lack of response using the MA and the values listed (15/40). I have found using an EMA with 5/35 to be more responsive.

Cheers


----------



## captain black (20 May 2010)

Superboot said:


> I hear what you are saying about the lack of response using the MA and the values listed (15/40). I have found using an EMA with 5/35 to be more responsive.




Another option worth testing as an index filter is using the close of the All Ords crossing below an EMA rather than a cross of 2 ema's. My index filter closed all trades in the last week of April, I've been 100% cash since then waiting for the next leg up when the All Ords crosses above the filter line. My  ... only real way to know is to test it, mine's worked for me for the last 9 years.


----------



## Wysiwyg (26 May 2010)

Wysiwyg said:


> Have you considered using the Correlation function? I had improved results using position score with it. Though I know what correlation means, the explanation in AMI.'s Help suggests correlation between two arrays. That being the Index Close and the Stock Close for the period of 20.



On second thoughts I think the Position Score function is a bit of a gimmick. I much prefer hand picking the final selection. 


> 3. Trade delays - It is crucial to get this right. . I do intraday trading so I get my signals at night and enter buy/sell signals the next day. If doing Intraday trading set your trade delays as follows:
> SetTradeDelays(1,1,1,1);



When finally paper trading a system it is feasible to run the exploration at 4.01 pm and buy in the after-market auction. I haven't sampled a great deal for comparing to buy-next-day. 


> And quite a difference that makes. The S&P 500 has predominantly higher dollar per share stocks than the Oz market. This factor alone produces radically different results.



Well I assumed the higher dollar values to be a contributing factor but really the percentage of price movement shouldn't be altered with higher dollar values.  A $1 stock moves 20% as does a $30 stock move 20%, etc, etc. I must have had a hold of the ol' fella while thinking that.  



> Superboot
> Re: Trading strategy development - Lessons Learnt
> Hey Wysiwyg,
> 
> Can I pose a question - if you didn't have an index filter and stayed in a falling market would you be better/worse off?



History shows that markets do recover and a buy and hold of quality stock would work.

ROE, the best poster on this forum, is worth having a read of.


----------



## Dracuu (27 May 2010)

Great thread with lots of good points.

I am yet to read your book Howard but I will be putting an order in tomorrow.

"TickSize" is another parameter I use to ensure accuracy but not overly important especially if you filter out cheaper stocks.

I developed my own "correlation matrix" which I will eventualy make public as a website. 
It basically retrieves prices from a database for whatever stocks you select and using the time frame you choose ie. hourly or daily and over a period you select ie. 1 week, 3 months, 5 years etc. and checks the correlation between these stocks. (It does much more but I won't get into that).

If I have to use my discretion to select a trade out of all valid entry signals then I will select a trade that shows the least correlation with the stocks I am already in.
I figure that by choosing a stock that shows the least correlation to the other stocks you already have "theoretically" should reduce my maximum draw down and so far it appears to be working in this way. Obviously it could also work against me in regards to overall profit but Max DD is very important to me.
I am yet to back test it but eventually I want to somehow code it into amibroker.


----------



## Wysiwyg (27 May 2010)

Dracuu said:


> Obviously it could also work against me in regards to overall profit but Max DD is very important to me.
> I am yet to back test it but eventually I want to somehow code it into amibroker.




You're worse than my ISP.   They know where I have been on the internet and as another matter of fact I have been searching for a MaxDD stop for my strategy testing. An ultimate stop to trading when the MaxDD is greater than 15% for example. Most of my draw-down happens before the indicator stop is triggered, before the market index price has fallen over.


----------

