It is a dream of mine to have a robot that optimized itself, that way I would know that it was always working with the best values. This is my humble attempt to bring a piece of my dream into reality. The attached expert advisor optimizes the overbought and oversold levels that it uses to make trades. It is my wish that others could take this concept and expand on it to create something even greater if you do, please let me know about it. Also, don't forget to rate my robot using the stars above. This strategy is applicable to any currency pair using any time frame with of course the correct settings.
There are quite a few inputs listed for this robot. I've included some extra features, that I like to play around with, enjoy.
- magic = 4376 - Unique number for this EA.
- optomizingPeriods = 144 - Optimization periods (bars). This is the number of bars you would like the optimization to run on. For example, if you are using an hourly chart and you choose 144, the robot will look back 144 hours which equates to six days.
- inAggressive = false - Make expert aggressive? Risky. Aggressive mode will cause the expert advisor to take trades in a more aggressive manner. Instead of waiting for a cross of the overbought or oversold level in the aggressive mode the robot will take a buy trade simply if the buys have been more profitable than the sells lately and vice versa.
- inTradeReverse = false - Reverse trading. Reverse trading will switch the direction of your trades.
- inOneOrderAtATime = true - Only one order open at a time?. If true the robot will only have one order at a time, if false it will open unlimited amounts of order according to entry conditions.
- Lot_sizing_dynamic_invalidates_static - Simply a spacer to separate Lot sizing mechanics from the other inputs.
- Lots = 0.01 - Static Lot size of orders. Specify the lot size for your orders using a static number.
- inUseDynamicLotSize = true - Use Dynamic lot sizing. Turns on dynamic lot sizing which would be used instead of static lot sizing, However, if the dynamic lots size proves to be invalid the robot will default to the static lot size.
- inPercentageOfRisk = 2 - Balance % to risk on each trade (2 = 2%). When using dynamic lot sizing you specify your lot size as a percentage of your balance. 2 is equal to 2 percent. No need to enter 0.02 if you do enter it in that way the percentage used would be very small indeed. The maximum percentage that can be used is 10 percent.
- Index_Indicator_Values - Simply a spacer to separate index indicator parameters from other inputs.
- indicator index = _RSI_ - Choose which index indicator to use. Allow you to choose which indicator you would like to use current choices are Relative Strength Index (RSI) or Money Flow Index (MFI).
- IndicatorTopValue = 100 - Top most value you would trade at. This the uppermost value you would place a trade at using your indicator. Leave it at 100 to consider all the index indicator values.
- IndicatorBottomValue = 0 - Bottom most value you would trade at. This is the bottom-most value you would place a trade at using your indicator. Leave it at 0 to consider all the index indicator values.
- IndyTimeframe = PERIOD_CURRENT - Timeframe for index. Select which time frame you would like to use for the indicator during optimization and trading. PERIOD_CURRENT simply means that it would use the time frame of the chart that you attach the expert advisor to. You could theoretically use a time frame for your calculations that is different from the chart you attach the robot to if you wish to do so here is where you would change that setting.
- inIndyPeriods = 14 - Averaging period for index and ATR calculations. Average True Range (ATR) is used in setting a dynamic stop-loss or take-profit in further input options below.
- IndyAppPrice = PRICE_CLOSE - Applied price for index if needed.
- SL_TP_Dynamic_invalidates_static_values - Simply a spacer to separate stop loss and take profit parameters from other inputs.
- iStoploss = 1000 - Static Stoploss value in points. Stop loss values are in points which is the smallest unit of movement in your terminal.
- iTakeprofit = 2000 - Static Takeprofit value in points. Take profit values are in powhich is the smallest unit of movement in your terminal.
- input inDynamic = true - Use Dynamic sp & tp based on ATR multiple? If you turn on the dynamic stop loss and take profit they will be used instead of the static stop loss or take profit. Dynamic settings can be attractive because they have the ability to adjust according to market behavior. Since the ATR is larger when there is more movement, using dynamic would result in larger stop losses and take profits when the market is moving fast and closer settings when the market has slowed down.
- inStoplossMultiple = 2 - Dynamic SL = X * ATR (Averaging Period). The stop loss will be the value you place here multiplied by the Average True Range (ATR) using the periods specified in the inIndyPeriods - input setting.
- inTakeProfitMultiple = 7 - Dynamic TP = X * ATR (Averaging Period). The take profit will be the value you place here multiplied by the Average True Range (ATR) using the periods specified in the inIndyPeriods - input setting.
- Break_Even_Settings - Padding must be lower than Trigger. A separator for Break even settings. The way it works is when points in profits go above the trigger amount the stop loss is moved to break even. If you have a padding setting then the stop loss is moved to break even + padding to lock in the padding amount of profit.
- bUseBreakEven = true - Use Break Even (BE). Turn the use of break even on or off.
- inTrigger = 200 - If BE = [true] set Points in profit to trigger. If the trade gets to these many points in profit the stop loss will be moved to break even.
- inPadding = 100 - Padding points to add to BE must be lower than trigger. This is a number of points of profit you want to lock in when moving to break even, this amount must be less than the trigger.
How does this robot self-optimize? Here is the secret, the robot tests each variable in the index indicator twice, so if an indicator has one hundred possible values it takes each value and tries to perform a trade at that value going back a certain number of bars (optomizingPeriods). Then it grades that value by how much money it would have won or lost by trading at that value. It is a bit more complex than that, but you are reading this to get more details so here it is as follows.
The givens are that when an indicator crosses the overbought value from the top, a sell order is issued, a buy order is issued when an indicator crosses from below an oversold value to above an oversold value. For example, if overbought was set to 80 and the value of your indicator was 85 on the bar before last and the value of the indicator on the last bar was 79 then a sell order would be issued. 85 → 79 crosses 80 downwards, sell order issued. If oversold = 23 then 19 → 27 upwards would create a buy order.
So, this robot takes every value for the indicator from the IndicatorTopValue - and IndicatorBottomValue - and runs a test, two tests more specifically. It runs a buy and sell test on each value. For example, if the top value is 100 it takes the top value and backtests it on the optomizingPeriods, let's say that is 144 periods. So it would see if buying at 100 and selling at 100 would have been profitable in the last 144 periods. If it is profitable, it retains that dollar amount.
Considering how many periods you are back testing it may have had the opportunity to buy multiple times during the backtest. If it hits the take profit before it hits the stop loss then it would have a profitable result if it hits the stop loss before the take profit it has a negative result. After testing all the periods in the optomizingPeriods - it adds all the profitable results with all the losses to retain a monetary value. Then the indicator moves on to the next lower indicator value and tests it for profitability.
When it has tested all the values it selects the value with the highest monetary amount and chooses it as the optimal buy-value. Next, it performs similar checks for the sell-value. When this is complete it compares the best buy-value with the best sell-value and looks for a trade that is the best of the best. So for example after running this optimization it determines that the best buy would be at 65 because a buy at 65 generated the most profit for buys, lets say $329 in backtesting it would check the value it has for best sell, and if best sell was 32 with a profit of $530 the robot would look for sell trade with the indicator crossing the 32 level because to sell is better than to buy according to profits generated in the backtest.
The Future Expansion Ideas
- Trade multiple currency pairs at the same time, possibly filtered by spread size.
- Self-learning, whereby it learns from its own trades what is best.
- Backtesting could also include a forward testing component.
- More indicators to choose from.
Please leave your suggestions and comments, and don't forget to rate!
Now available in the MetaTrader marketplace: https://www.mql5.com/en/market/product/26332
Updated with missing brackets in lines 137-142 to resolve error identified in comments.