Categories
Forex Education Forex Indicators Forex System Design

Designing a Trading Strategy – Part 3

Introduction

In our previous article, we presented the first component of a trading strategy, which corresponds to the market entry and exit rules. Likewise, we exposed the case of a basic trading system based on the crossing of two moving averages.

In this educational article, we will present the filters and how they can help the trader refine a trading strategy.

600x600

Setting Additional Filters in Trading Strategy

Signals originated in a trading strategy can use filters to improve the entry or exit signals that the system generates. The purpose of incorporating filters is to improve both the accuracy and reliability of the strategy. 

A filter can be an indicator’s level or additional instructions to the initial entry, or exit rules. Some examples of filters can be:

  1. Avoid buy entries if the reading of the 60-period RSI oscillator is less than 49. 
  2. Allow Buy entries if the price closes above the high of the previous day or allow sell-short signals if the price closes below the last day’s low.

Also, rules can be established to control the strategy’s risk, and preserve the trading account’s capital. In this context, two elements that can help to manage the risk are:

  1. Initial stop-loss, which can be a fixed amount of pips or depending on some previous periods’ volatility. In turn, this rule can be fixed or dynamic, its level moving as the trade progresses through time.
  2. limiting the number of simultaneously opened trades. This rule can be useful, mainly when the market moves in a sideways path.

Measuring the Risk of Strategy

The risk of trading strategy corresponds to the amount of capital that the investor risks with the expectation of a possible return on the financial market by applying a set of rules with positive expectations.

One way to measure the risk of trading strategy is through the maximum drawdown, which corresponds to the maximum drop in equity from the peak of the equity value to the subsequent equity low.

The developer can obtain this measure as well as other strategy performance indicators by running a historical simulation.

Incorporating Additional Rules into Trading Strategy

The following example corresponds to the addition of rules to the trading strategy formulated and developed in the previous article, based on  moving averages crossovers with 5 and 55 periods. 

Before incorporating additional rules and evaluating their subsequent impact on the trading strategy, we will display the results of a historical simulation, developed using the EURUSD pair in its hourly timeframe. Likewise, the size of each trade position corresponded to 0.1 lot in a $10,000 account.

The following figure illustrates the strategy’s performance in its initial condition, which executed 652 trades providing a drawdown level of 22.66% and a net profit of -$716.93.

The additional proposed filter rules are as follows:

  • The strategy must have an initial stop loss of 30 pips. This stop will limit the possible maximum amount of loss per trade.
extern double SL_Pips = 30;
  • We propose using a Break-Even rule to ensure the opened trades’ profits, which will be used when the price advances 40 pips. Likewise, the strategy will apply a Trailing Stop of 40 pips of advance and a 3-pips step
extern double BreakEven_Pips = 40;
extern double Trail_Pips = 40;
extern double Trail_Step = 3;

The function that computes the Trailing Stop is as follows:

void TrailingStopTrail(int type, double TS, double step, bool aboveBE, double 
aboveBEval) //set Stop Loss to "TS" if price is going your way with "step"
  {
   int total = OrdersTotal();
   TS = NormalizeDouble(TS, Digits());
   step = NormalizeDouble(step, Digits());
   for(int i = total-1; i >= 0; i--)
     {
      while(IsTradeContextBusy()) Sleep(100);
      if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
      if(OrderMagicNumber() != MagicNumber || OrderSymbol() != 
Symbol() || OrderType() != type) continue;
	  RefreshRates();
      if(type == OP_BUY && (!aboveBE || Bid > OrderOpenPrice() + TS + aboveBEval)
 && (NormalizeDouble(OrderStopLoss(), Digits()) <= 0 ||
 Bid > OrderStopLoss() + TS + step))
         myOrderModify(OrderTicket(), Bid - TS, 0);
      else if(type == OP_SELL && (!aboveBE || Ask < OrderOpenPrice()
 - TS - aboveBEval) && (NormalizeDouble(OrderStopLoss(), Digits()) <= 0 ||
 Ask < OrderStopLoss() - TS - step))
         myOrderModify(OrderTicket(), Ask + TS, 0);
     }
  }
  • Also, the strategy must allow a maximum limit of one trade at a time.
extern int MaxOpenTrades = 1;

In this context, the code that will determined the limit reached will be as follows:

   //test maximum trades
   if((type % 2 == 0 && long_trades >= MaxLongTrades)
   || (type % 2 == 1 && short_trades >= MaxShortTrades)
   || (long_trades + short_trades >= MaxOpenTrades)
   || (type > 1 && type % 2 == 0 && long_pending >= MaxLongPendingOrders)
   || (type > 1 && type % 2 == 1 && short_pending >= MaxShortPendingOrders)
   || (type > 1 && long_pending + short_pending >= MaxPendingOrders)
   )
     {
      myAlert("print", "Order"+ordername_+" not sent, maximum reached");
      return(-1);
     }
  • The trading strategy must preserve the account equity using a position size that should be proportional to 1 lot per $100,000 of equity.
extern double MM_PositionSizing = 100000;
double MM_Size() //position sizing
  {
   double MaxLot = MarketInfo(Symbol(), MODE_MAXLOT);
   double MinLot = MarketInfo(Symbol(), MODE_MINLOT);
   double lots = AccountBalance() / MM_PositionSizing;
   if(lots > MaxLot) lots = MaxLot;
   if(lots < MinLot) lots = MinLot;
   return(lots);
  }

Now, the entry rules with the Stop-Loss rule will be as follows:

   //Open Buy Order, instant signal is tested first
   if(Cross(0, iMA(NULL, PERIOD_CURRENT, Period1, 0, MODE_LWMA, PRICE_CLOSE, 0) >
 iMA(NULL, PERIOD_CURRENT, Period2, 0, MODE_SMA, PRICE_CLOSE, 0)) 
//Moving Average crosses above Moving Average
   )
     {
      RefreshRates();
      price = Ask;
      SL = SL_Pips * myPoint; //Stop Loss = value in points (relative to price)   
      if(IsTradeAllowed())
        {
         ticket = myOrderSend(OP_BUY, price, MM_Size(), "");
         if(ticket <= 0) return;
        }
      else //not autotrading => only send alert
         myAlert("order", "");
      myOrderModifyRel(ticket, SL, 0);
     }
   
   //Open Sell Order, instant signal is tested first
   if(Cross(1, iMA(NULL, PERIOD_CURRENT, Period1, 0, MODE_LWMA, PRICE_CLOSE, 0) <
 iMA(NULL, PERIOD_CURRENT, Period2, 0, MODE_SMA, PRICE_CLOSE, 0))
 //Moving Average crosses below Moving Average
   )
     {
      RefreshRates();
      price = Bid;
      SL = SL_Pips * myPoint; //Stop Loss = value in points (relative to price)   
      if(IsTradeAllowed())
        {
         ticket = myOrderSend(OP_SELL, price, MM_Size(), "");
         if(ticket <= 0) return;
        }
      else //not autotrading => only send alert
         myAlert("order", "");
      myOrderModifyRel(ticket, SL, 0);
     }
  }

Finally, the position’s closing code including the trailing stop will be as follows:

  {
   int ticket = -1;
   double price;   
   double SL;
   
   TrailingStopTrail(OP_BUY, Trail_Pips * myPoint, Trail_Step * myPoint, false,
 0); //Trailing Stop = trail
   TrailingStopTrail(OP_SELL, Trail_Pips * myPoint, Trail_Step * myPoint, false,
 0); //Trailing Stop = trail
   
   //Close Long Positions
   if(iMA(NULL, PERIOD_CURRENT, Period1, 0, MODE_LWMA, PRICE_CLOSE, 0) <
 iMA(NULL, PERIOD_CURRENT, Period2, 0, MODE_SMA, PRICE_CLOSE, 0)
 //Moving Average < Moving Average
   )
     {   
      if(IsTradeAllowed())
         myOrderClose(OP_BUY, 100, "");
      else //not autotrading => only send alert
         myAlert("order", "");
     }
   
   //Close Short Positions
   if(iMA(NULL, PERIOD_CURRENT, Period1, 0, MODE_LWMA, PRICE_CLOSE, 0) >
 iMA(NULL, PERIOD_CURRENT, Period2, 0, MODE_SMA, PRICE_CLOSE, 0)
 //Moving Average > Moving Average
   )
     {   
      if(IsTradeAllowed())
         myOrderClose(OP_SELL, 100, "");
      else //not autotrading => only send alert
         myAlert("order", "");
     }

The historical simulation with the inclusion of the additional rules to the trading strategy  is illustrated in the next figure and reveals a reduction in the Drawdown from 22.66% to 10.49%. Likewise, we distinguish a variation in the Total Net Profit from -$716.93 to -$413.76.

Although the trading strategy continues having a negative expectation, This exercise shows the importance of including additional rules to improve the trading strategy’s performance.

Conclusions

This educational article presented how the inclussion of filters into a trading strategy can improve the performance of two key indicators such as the Drawdown and the Total Net Profit.

On the other hand, we did not consider the parameters optimization during this step. Optimization will be discussed in a future article.

In the next educational article, we will extend the concepts of Profits Management and Position Sizing.

Suggested Readings

  • Jaekle, U., Tomasini, E.; Trading Systems: A New Approach to System Development and Portfolio Optimisation; Harriman House Ltd.; 1st Edition (2009).
  • Pardo, R.; The Evaluation and Optimization of Trading Strategies; John Wiley & Sons; 2nd Edition (2008).
970x250

By Eduardo Vargas

Eduardo Vargas is a technical analyst and independent trader based in Buenos Aires, Argentina. He is an Industrial Engineer and holds a Master in Finance degree. In 2008 began to trade Chilean stocks listed on IPSA. From 2013 started to trade CFDs on Forex, Commodities, Indices and ETFs markets. He analyses different markets combining the Elliott Wave analysis with Fibonacci tools. He provides a market mid-long-term vision.

Leave a Reply

Your email address will not be published. Required fields are marked *