Adding entry filters to your strategies
Forums › ProRealTime English forum › General trading discussions › Adding entry filters to your strategies
- This topic has 7 replies, 4 voices, and was last updated 8 months ago by SweTrade.
-
-
02/20/2024 at 2:46 PM #228456
Hello!
I just watched a Youtube video regarding algo trading, this one: https://youtu.be/rrbahhoePN4?si=XG19Aw7iqNPj5Spe&t=4500
What crossed my mind is that he says he tries to make good strategies great with a filter optimization. The way he does it, is to try 500 different filters on the strategy entries. Maybe your original trading idea works best in a low volatily market, or when the market is trending, or not trading it on mondays or if RSI is under/over 50 etc. He thought that this wasnt over-optimizing or curvefitting, only filtering which should be a good thing.
I’m very rookie at this, but if you try 200-500 different filters on 25-50% of your data, and you can confirm it on the rest of the data, you get 50-75% out of sample data as confirmation. Would that be “bad” curvefitting or good optimization? What are your opinions and thoughts on this?
02/20/2024 at 8:33 PM #228479I only watched the section you refer to above, but interesting stuff, likely I will watch the rest sometime!
What he didnt do though, was to keep the original Algo code as v1, duplicate v1 as v2, then add filter codes to v2, then run v1 and v2 … both over out of sample data.
Would that be “bad” curvefitting or good optimization?
It would be good optimisation if ‘out of sample’ results show increase at similar Gain % as the ‘in sample’ results.
Hope above makes sense, if not just say.
02/20/2024 at 11:12 PM #228486Thanks so much GraHal, it makes total sense! Not sure if its to any help, but I put together a list of some filters he show in the video as well some of my own ideas. Feel free to improve upon and add more. I plan to add some more filters regarding volume.
Algofilter123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163$algofilter[1] = close < average[5](close) // Below 5-Day Moving Average$algofilter[2] = close > average[5](close) // Above 5-Day Moving Average$algofilter[3] = close < average[10](close) // Below 10-Day Moving Average$algofilter[4] = close > average[10](close) // Above 10-Day Moving Average$algofilter[5] = close > average[10](close) // Above 10-Day Moving Average$algofilter[6] = close < average[21](close) // Below 21-Day Moving Average$algofilter[7] = close > average[21](close) // Above 21-Day Moving Average$algofilter[8] = close < average[30](close) // Below 30-Day Moving Average$algofilter[9] = close > average[30](close) // Above 30-Day Moving Average$algofilter[10] = close < average[40](close) // Below 40-Day Moving Average$algofilter[11] = close > average[40](close) // Above 40-Day Moving Average$algofilter[12] = close < average[50](close) // Below 50-Day Moving Average$algofilter[13] = close > average[50](close) // Above 50-Day Moving Average$algofilter[14] = close < average[75](close) // Below 75-Day Moving Average$algofilter[15] = close > average[75](close) // Above 75-Day Moving Average$algofilter[16] = close < average[100](close) // Below 100-Day Moving Average$algofilter[17] = close > average[100](close) // Above 100-Day Moving Average$algofilter[18] = close < average[200](close) // Below 200-Day Moving Average$algofilter[19] = close > average[200](close) // Above 200-Day Moving Average$algofilter[20] = time < 400 // Time Filter Before 4am$algofilter[21] = time < 600 // Time Filter Before 6am$algofilter[22] = time < 800 // Time Filter Before 8am$algofilter[23] = time < 1000 // Time Filter Before 10am$algofilter[24] = time < 1200 // Time Filter Before Noon$algofilter[25] = time > 400 // Time Filter After 4am$algofilter[26] = time > 600 // Time Filter After 6am$algofilter[27] = time > 800 // Time Filter After 8am$algofilter[28] = time > 1000 // Time Filter After 10am$algofilter[29] = time > 1200 // Time Filter After Noon$algofilter[30] = close[1] < close[2] and close[2] < close[3] and close[3] < close[4] // Four consecutive down closes$algofilter[31] = close[1] > close[2] and close[2] > close[3] and close[3] > close[4] and close[4] > close[5] // Five consecutive up closes$algofilter[32] = (high[0] - open[0]) > ((high[1] - open[1]) * 1) // Expansion 1$algofilter[33] = (high[0] - open[0]) > ((high[1] - open[1]) * 1.5) // Expansion 2$algofilter[34] = (open[0] - low[0]) > ((open[1] - low[1]) * 1) // Expansion 3$algofilter[35] = (open[0] - low[0]) > ((open[1] - low[1]) * 1.5) // Expansion 4$algofilter[36] = low[0] < low[1] // Low today trading below yesterday's low$algofilter[37] = close[1] < close[2] and close[2] < close[3] and close[3] < close[4] and close[4] < close[5] // Five consecutive down closes$algofilter[38] = high > highest[30](high[1]) // High today trading above yesterday's high$algofilter[39] = low < lowest[30](low[1]) // Low today trading below yesterday's low$algofilter[40] = abs(open[1] - close[1]) > 1.0 * (high[1] - low[1]) // Body > Yesterday's Range$algofilter[41] = abs(open[1] - close[1]) < 1.0 * (high[1] - low[1]) // Body < Yesterday's Range$algofilter[42] = close < lowest[5](low) // Close below lowest average lows$algofilter[43] = close > highest[5](high) // Close above highest average highs$algofilter[44] = lowest[1](low[1]) > 1 and close < lowest[1](low[1]) // Close is lower than the last Pivot Low$algofilter[45] = highest[1](high[1]) > 1 and close > highest[1](high[1]) // Close is greater than the last Pivot High$algofilter[46] = summation[5](close) >= BollingerUp[20](close) // Consecutive closes are either at or higher than the upper Bollinger Band$algofilter[47] = summation[5](close) <= BollingerDown[20](close) // Consecutive closes are either at or lower than the lower Bollinger Band$algofilter[48] = summation[3](close > open) = 3 // Consecutive number of bars which went Up (Close > Open)$algofilter[49] = summation[3](close < open) = 3 // Consecutive number of bars which went Down (Close < Open)$algofilter[50] = summation[3](close > close[1]) = 3 // Consecutive Up Close$algofilter[51] = summation[3](close < close[1]) = 3 // Consecutive Down Close$algofilter[52] = summation[5](high > highest[30](high[1])) >= 5 // Consecutive number of bars with High > highest in the last 30 bars$algofilter[53] = summation[5](low < lowest[30](low[1])) >= 5 // Consecutive number of bars with Low < lowest in the last 30 bars$algofilter[54] = highest[10](close) < lowest[10](close) // Consecutive highest High within the last 10 bars followed by consecutive lowest Low within the last 10 bars$algofilter[55] = highest[10](close) > lowest[10](close) // Consecutive lowest Low within the last 10 bars followed by consecutive highest High within the last 10 bars$algofilter[56] = high > highest[5](high) // Current Bar is highest high in the last 5 bars$algofilter[57] = low < lowest[5](low) // Current Bar is lowest low in the last 5 bars$algofilter[58] = highest[10](close) > lowest[10](close) // Highest Close After Lowest Close$algofilter[59] = highest[10](close) < lowest[10](close) // Highest Close Before Lowest Close$algofilter[60] = high > highest[5](high) // Current Bar is highest high in the last 5 bars$algofilter[61] = low < lowest[5](low) // Current Bar is lowest low in the last 5 bars$algofilter[62] = highest[10](high) > lowest[10](high) // Highest High After Lowest High$algofilter[63] = highest[10](low) < lowest[10](low) // Highest Low After Lowest Low$algofilter[64] = highest[10](low) > lowest[10](low) // Highest Low Before Lowest Low$algofilter[65] = average[20](close) > average[20](close)[1] and average[20](close)[1] > average[20](close)[2] // MA > MA[1]$algofilter[66] = average[20](close) < average[20](close)[1] and average[20](close)[1] < average[20](close)[2] // MA < MA[1]$algofilter[67] = average[20](close) < average[20](close)[1] and average[20](close)[1] < average[20](close)[2] // MA < MA[1]$algofilter[68] = (high - low)[1] > (high - low)[2] and (high - low) > (high - low)[1] // Range Expansion Followed By Contraction$algofilter[69] = (high - low)[1] < (high - low)[2] and (high - low) < (high - low)[1] // Range Contraction Followed By Expansion$algofilter[70] = close > highest[5](close) // Highest Close 5 Bars$algofilter[71] = close < lowest[5](close) // Lowest Close 5 Bars$algofilter[72] = highest[3](high) <= 0.20 * (highest[3](high) - lowest[3](low)) // Art Collins: Highs of the last 3 bars greater than 20% range of the last 3 bars$algofilter[73] = highest[3](low) <= 0.20 * (highest[3](high) - lowest[3](low)) // Art Collins: Lows of the last 3 bars greater than 20% range of the last 3 bars$algofilter[74] = highest[50](high[2]) <> 1 and lowest[50](low[2]) <> 1 and highest[50](high[2]) <> 1 // No pivot high and pivot low in the last 50 bars$algofilter[75] = lowest[50](low[2]) <> 1 and highest[50](high[2]) <> 1 and lowest[50](low[2]) <> 1 // No pivot low and pivot high in the last 50 bars$algofilter[76] = summation[5](rsi[14](close) > 50) >= 5 // RSI stays above threshold$algofilter[77] = summation[5](rsi[14](close) < 50) >= 5 // RSI stays below threshold$algofilter[78] = rsi[7](close) >= 75 // PercentR Overbought$algofilter[79] = rsi[7](close) <= 25 // PercentR Oversold$algofilter[80] = rsi[14](close) >= 75 // RSI Overbought$algofilter[81] = rsi[14](close) <= 25 // RSI Oversold$algofilter[82] = rsi[3](close) > 75 // Short RSI Overbought$algofilter[83] = rsi[3](close) < 75 // Short RSI Overbought Reverse$algofilter[84] = rsi[3](close) > 25 // Short RSI Oversold Reverse$algofilter[85] = rsi[3](close) < 25 // Short RSI Oversold$algofilter[86] = ((close - close[10]) / close[10]) * 100 <= 5 // Rate of change lower than a threshold$algofilter[87] = ((close - close[10]) / close[10]) * 100 > 5 // Rate of change greater than a threshold$algofilter[88] = momentum[10](close[1]) < 0 // Low Momentum$algofilter[89] = momentum[10](close[1]) > 0 // High Momentum$algofilter[90] = adx[15] > 30 // ADX > 30$algofilter[91] = adx[15] < 30 // ADX < 30$algofilter[92] = adx[15] > 10 // ADX > 10$algofilter[93] = adx[15] < 10 // ADX < 10$algofilter[94] = macd[10, 30, 9](close) < average(macd[10, 30, 9]) // MACD < MACD Threshold$algofilter[95] = macd[10, 30, 9](close) > average(macd[10, 30, 9]) // MACD > MACD Threshold$algofilter[96] = close[1] < average[5](close) and close[1] > average[20](close) // Dueling Momentum Low High$algofilter[97] = close[1] > average[5](close) and close[1] < average[20](close) // Dueling Momentum High Low$algofilter[98] = average[5](high - low) < average[20](high - low) // One Average Range is smaller than another Average Range$algofilter[99] = average[5](high - low) > average[20](high - low) // One Average Range is bigger than another Average Range$algofilter[100] = ((low[1] < low[2]) and (low[1] < low[3]) and (low[1] < low[4]))$algofilter[101] = ((low[1] > low[2]) and (low[1] > low[3]) and (low[1] > low[4]))$algofilter[102] = (average[2](close) < average[5](close)) // Two-Day Lower Than Five-Day$algofilter[103] = (average[2](close) > average[5](close)) // Two-Day Greater Than Five-Day$algofilter[104] = (average[10](close) < average[20](close)) // Ten-Day Lower Than Twenty-Day$algofilter[105] = (average[10](close) > average[20](close)) // Ten-Day Greater Than Twenty-Day$algofilter[106] = ((close > highest[50](close)) and (close > highest[50](close)[1])) // Close Over Last 50-Bar High$algofilter[107] = ((close < lowest[50](close)) and (close < lowest[50](close)[1])) // Close Under Last 50-Bar Low$algofilter[108] = ((close < lowest[50](close)) and (close < lowest[50](close)[1])) // Close Under Last 50-Bar Low$algofilter[109] = (close > average[50](close)) // Close Above 50-Day Average$algofilter[110] = (close < average[50](close)) // Close Below 50-Day Average$algofilter[111] = (close > highest[50](close)) // Close Above 50-Day High$algofilter[112] = (close < lowest[50](close)) // Close Below 50-Day Low$algofilter[113] = ((close > highest[200](close)) and (close > highest[200](close)[1])) // Close Over Last 200-Bar High$algofilter[114] = ((close < lowest[200](close)) and (close < lowest[200](close)[1])) // Close Under Last 200-Bar Low$algofilter[115] = (close > average[200](close)) // Close Above 200-Day Average$algofilter[116] = (close < average[200](close)) // Close Below 200-Day Average$algofilter[117] = (close > highest[200](close)) // Close Above 200-Day High$algofilter[118] = (close < lowest[200](close)) // Close Below 200-Day Low$algofilter[119] = ((close > highest[200](close)) and (close > highest[200](close)[1])) // Close Over Last 200-Bar High$algofilter[120] = ((close < lowest[200](close)) and (close < lowest[200](close)[1])) // Close Under Last 200-Bar Low$algofilter[121] = close > average[30](close) // Close Above 30-Day Average$algofilter[122] = close < average[30](close) // Close Below 30-Day Average$algofilter[123] = close > highest[30](close) // Close Above 30-Day High$algofilter[124] = close < lowest[30](close) // Close Below 30-Day Low$algofilter[125] = close > average[30](close) // Close Above 30-Day Average$algofilter[126] = close < average[30](close) // Close Below 30-Day Average$algofilter[127] = close > highest[30](close) // Close Above 30-Day High$algofilter[128] = close < lowest[30](close) // Close Below 30-Day Low$algofilter[129] = (low[1] < low[2] and low[1] < low[3] and low[1] < low[4]) // Lower Low$algofilter[130] = (high[1] > high[2] and high[1] > high[3] and high[1] > high[4]) // Higher High$algofilter[131] = (close[1] < close[2]) // Lower Close$algofilter[132] = (close[1] > close[2]) // Higher Close$algofilter[133] = (low[1] < low[2] and low[1] < low[3] and low[1] < low[4]) // Lower Low$algofilter[134] = (high[1] > high[2] and high[1] > high[3] and high[1] > high[4]) // Higher High$algofilter[135] = (close[1] < close[2]) // Lower Close$algofilter[136] = (close[1] > close[2]) // Higher Close$algofilter[137] = (low[1] < low[2] and low[1] < low[3] and low[1] < low[4]) // Lower Low$algofilter[138] = close > Average[2000] (close)$algofilter[139] = close < Average[2000] (close)$algofilter[140] = Not OpenDayOfWeek = 1 // if not Monday$algofilter[141] = Not OpenDayOfWeek = 2 // if not Tuesday$algofilter[142] = Not OpenDayOfWeek = 3 // if not Wednesday$algofilter[143] = Not OpenDayOfWeek = 4 // if not Thursday$algofilter[144] = Not OpenDayOfWeek = 5 // if not Friday$algofilter[145] = Not OpenDayOfWeek = 6 // if not Saturday$algofilter[146] = Not OpenDayOfWeek = 0 // if not Sunday$algofilter[147] = month <> 1 // Do not trade in January$algofilter[148] = month <> 2 // Do not trade in February$algofilter[149] = month <> 3 // Do not trade in March$algofilter[151] = month <> 4 // Do not trade in April$algofilter[152] = month <> 5 // Do not trade in May$algofilter[153] = month <> 6 // Do not trade in June$algofilter[154] = month <> 7 // Do not trade in July$algofilter[155] = month <> 8 // Do not trade in August$algofilter[156] = month <> 9 // Do not trade in September$algofilter[157] = month <> 10 // Do not trade in October$algofilter[158] = month <> 11 // Do not trade in November$algofilter[159] = month <> 12 // Do not trade in December// Add to your if statementand $algofilter[x]02/21/2024 at 9:24 AM #228490My take :
Of course the idea is nice. N.b.: There’s a similar example in the Library somewhere (of which I recall the idea again was nice but it got out of hand somehow).
ButMy brain wouldn’t be for something like this, because it “is” nothing. It can only be optimization (indeed), not hoping for the worse in the future. It is like GraHal suggest (reworded now) : pick one of the best you can find, especially don’t take another because you think it is out of whack (take your #20 as an example), and try NOT to think it will be rubbish.
And so it goes for all the examples.My thoughts about this are largely fed by working the other way around : observe some working strategies for a year in a row (I mean in Live Auto trades), see how some perform better than others, then try to find the merits of that, and improve on it (like ditching the worse performers and thus have a net better income). This is now forward-testing decision based (I am pretty sure GraHal knows all about this).
To even see better what I mean, envision that you really would put each of the filters into a Demo forward running test. For a year. Now, would you really do that ? or would you take some you deem better for any of your good reasons ? I think the latter, because else it will become too much.
We should try to wrap our heads around this too :
180K with ~700 trades in 11 years. This is an average revenue of +257 per trade (and is thus heavily optimized on top of it). What was the investment ? (maybe he tells this somewhere). Now you can go two directions : 1. the DD of 10K after trade #100 is OK-ish because the investment is 100K and this DD of 10% in that (estimated) year is fine. But wait, if I invest 100K I don’t want 180K in 11 years. So 2. the investment is only 10K and the revenue of 180K in 11 years could be acceptable. But now the DD of 10K in that estimated one year is not acceptable at all.
If people have more justifiable scenario’s – I am all ears.02/21/2024 at 10:15 AM #228492TIME is formatted as HHMMSS, thus 040000 is 40000, not 400 and 100000 is just 100000.
1 user thanked author for this post.
02/21/2024 at 6:44 PM #228524Not sure if its to any help, but I put together a list of some filters
Looks well good, but how do we use these in a strategy which then allows the optimiser to give results for each Filter?
02/21/2024 at 6:55 PM #22852802/21/2024 at 11:28 PM #228532 -
AuthorPosts
Find exclusive trading pro-tools on