Subscribe to DSC Newsletter

Forex Algorithmic Trading: A Practical Tale for Engineers

A few years ago, driven by my curiosity, I took my first steps into the world of Forex trading algorithms by creating a demo account and playing out simulations (with fake money) on the Meta Trader 4 trading platform.

After a week of ‘trading’, I’d almost doubled my money. Spurred on by my own success, I dug deeper and eventually signed up for a number of forums. Soon, I was spending hours reading about algorithmic trading systems (rule sets that determine whether you should buy or sell), custom indicators, market moods, and more.

My First Client

Around this time, coincidentally, I heard that someone was trying to find a software developer to automate a simple trading system. This was back in my college days when I was learning about concurrent programming in Java (threads, semaphores, and all that junk). I thought that this automated system this couldn’t be much more complicated than my advanced data science course work, so I inquired about the job and came on-board.

The client wanted the system built with MQL4, a functional programming language used by the Meta Trader 4 platform for performing stock-related actions.

MQL5 has since been released. As you might expect, it addresses some of MQL4's issues and comes with more built-in functions, which makes life easier.

The role of the trading platform (Meta Trader 4, in this case) is to provide a connection to a Forex broker. The broker then provides a platform with real-time information about the market and executes your buy/sell orders. For readers unfamiliar with Forex trading, here’s the information that is provided by the data feed:

Through Meta Trader 4, you can access all this data with internal functions, accessible in various timeframes: every minute (M1), every five minutes (M5), M15, M30, every hour (H1), H4, D1, W1, MN.

The movement of the Current Price is called a tick. In other words, a tick is a change in the Bid or Ask price for a currency pair. During active markets, there may be numerous ticks per second. During slow markets, there can be minutes without a tick. The tick is the heartbeat of a Forex robot.

When you place an order through such a platform, you buy or sell a certain volume of a certain currency. You also set stop-loss and take-profit limits. The stop-loss limit is the maximum amount of pips (price variations) that you can afford to lose before giving up on a trade. The take-profit limit is the amount of pips that you’ll accumulate in your favor before cashing out.

If you want to learn more about the basics of trading (e.g., pips, order types, spread, slippage, market orders, and more), see here.

The client’s algorithmic trading specifications were simple: they wanted a robot based on two indicators. For background, indicators are very helpful when trying to define a market state and make trading decisions, as they’re based on past data (e.g., highest price value in the last n days). Many come built-in to Meta Trader 4. However, the indicators that my client was interested in came from a custom trading system.

They wanted to trade every time two of these custom indicators intersected, and only at a certain angle.

Hands On

As I got my hands dirty, I learned that MQL4 programs have the following structure:

  • [Preprocessor Directives]
  • [External Parameters]
  • [Global Variables]
  • [Init Function]
  • [Deinit Function]
  • [Start Function]
  • [Custom Functions]

The start function is the heart of every MQL4 program since it is executed every time the market moves (ergo, this function will execute once per tick). This is the case regardless of the timeframe you’re using. For example, you could be operating on the H1 (one hour) timeframe, yet the start function would execute many thousands of times per timeframe.

To work around this, I forced the function to execute once per period unit:

int start()
{  if(currentTimeStamp == Time[0]) return (0);
  
  currentTimeStamp  = Time[0];

...

 

Getting the values of the indicators:

// Loading the custom indicator
extern string indName = "SonicR Solid Dragon-Trend (White)";
double dragon_min;
double dragon_max;
double dragon;
double trend;
int start()
{  


 // Updating the variables that hold indicator values
 actInfoIndicadores();

….


string actInfoIndicadores()
{  
   dragon_max=iCustom(NULL, 0, indName, 0, 1);
   dragon_min=iCustom(NULL, 0, indName, 1, 1);
   dragon=iCustom(NULL, 0, indName, 4, 1);
   trend=iCustom(NULL, 0, indName, 5, 1);
}

The decision logic, including intersection of the indicators and their angles:

int start()
{

  if(ticket==0)
  {  
        if (dragon_min > trend && (ordAbierta== "OP_SELL" || primeraOP == true) && anguloCorrecto("BUY") == true && DiffPrecioActual("BUY")== true ) {
           primeraOP =  false;
           abrirOrden("OP_BUY", false);
        }
        if (dragon_max < trend && (ordAbierta== "OP_BUY" || primeraOP == true) && anguloCorrecto("SELL") == true && DiffPrecioActual("SELL")== true ) {
           primeraOP = false;
           abrirOrden("OP_SELL", false);
        }  
  }     
  else
  {       
      if(OrderSelect(ticket,SELECT_BY_TICKET)==true)
      {
          datetime ctm=OrderCloseTime();
          if (ctm>0) {
             ticket=0;
             return(0);
          }
      }
      else
         Print("OrderSelect failed error code is",GetLastError());

      if (ordAbierta == "OP_BUY"  && dragon_min <= trend  ) cerrarOrden(false);
      else if (ordAbierta == "OP_SELL" && dragon_max >= trend ) cerrarOrden(false);
  }
}

Sending the orders:

void abrirOrden(string tipoOrden, bool log)
{  
  RefreshRates();
  double volumen = AccountBalance() * point;
  double pip     = point * pipAPer;   
  double ticket  = 0;
  while( ticket <= 0)
  {  if (tipoOrden == "OP_BUY")   ticket=OrderSend(simbolo, OP_BUY,  volumen, Ask, 3, 0/*Bid - (point * 100)*/, Ask + (point * 50), "Orden Buy" , 16384, 0, Green);
     if (tipoOrden == "OP_SELL")  ticket=OrderSend(simbolo, OP_SELL, volumen, Bid, 3, 0/*Ask + (point * 100)*/, Bid - (point * 50), "Orden Sell", 16385, 0, Red);
     if (ticket<=0)               Print("Error abriendo orden de ", tipoOrden , " : ", ErrorDescription( GetLastError() ) );
  }  ordAbierta = tipoOrden;
  
  if (log==true) mostrarOrden();
}

If you’re interested, you can find the complete, runnable code on GitHub.

 

Back-Testing

Once I built my algorithmic trading system, I wanted to know: 1) if it was behaving appropriately, and 2) if it was any good.

Back-testing is the process of testing a particular (automated or not) system under the events of the past.In other words, you test your system using the past as a proxy for the present.

MT4 comes with an acceptable tool for back-testing a Forex trading system (nowadays, there are more professional tools that offer greater functionality). To start, you setup your timeframes and run your program under a simulation; the tool will simulate each tick knowing that for each unit it should open at certain price, close at a certain price and, reach specified highs and lows.

After comparing the actions of the program against historic prices, you’ll have a good sense for whether or not it’s executing correctly.

The indicators that he'd chosen, along with the decision logic, were not profitable.

From back-testing, I’d checked out the robot’s return ratio for some random time intervals; needless to say, I knew that my client wasn’t going to get rich with it—the indicators that he’d chosen, along with the decision logic, were not profitable. As a sample, here are the results of running the program over the M15 window for 164 operations:

Note that our balance (the blue line) finishes below its starting point.

One caveat: saying that a system is "profitable" or "unprofitable" isn't always genuine. Often, systems are (un)profitable for periods of time based on the market's "mood":

Parameter Optimization, and its Lies

Although back-testing had made me wary of this robot’s usefulness, I was intrigued when I started playing around with its external parameters and noticed big differences in the overall Return Ratio. This particular science is known as Parameter Optimization.

I did some rough testing to try and infer the significance of the external parameters on the Return Ratio and came up with something like this:

Or, cleaned up:

You may think (as I did) that you should use the Parameter A. But the decision isn’t as straightforward as it may appear. Specifically, note the unpredictability of Parameter A: for small error values, its return changes dramatically. In other words, Parameter A is very likely to over-predict future results since any uncertainty, any shift at all will result in worse performance.

But indeed, the future is uncertain! And so the return of Parameter A is also uncertain. The best choice, in fact, is to rely on unpredictability. Often, a parameter with a lower maximum return but superior predictability (less fluctuation) will be preferable to a parameter with high return but poor predictability.

The only thing you can be sure is that you don’t know the future of the market, and thinking you know how the market is going to perform based on past data is a mistake. In turn, you must acknowledge this unpredictability.

Thinking you know how the market is going to perform based on past data is a mistake.

This does not necessarily mean we should use Parameter B, because even the lower returns of Parameter A performs better than Parameter B; this is just to show you that Optimizing Parameters can result in tests that overstate likely future results, and such thinking is not obvious.

Overall Forex Algorithmic Trading Considerations

Since that first algorithmic Forex trading experience, I’ve built several automated trading systems for clients, and I can tell you that there’s always room to explore. For example, I recently built a system based on finding so-called “Big Fish” movements; that is, huge pips variations in tiny, tiny units of time. This is a subject that fascinates me.

Building your own simulation system is an excellent option to learn more about the Forex market, and the possibilities are endless. For example, you could try to decipher the probability distribution of the price variations as a function of volatility in one market (EUR/USD for example), and maybe make a Montecarlo simulation model using the distribution per volatility state, using whatever degree of accuracy you want. I’ll leave this as an exercise for the eager reader.

The Forex world can be overwhelming at times, but I hope that this write-up has given you some points on how to get going.

Further Reading

Nowadays, there is a vast pool of tools to build, test, and improve Trading System Automations: Trading Bloxfor testing, NinjaTrader for trading, OCaml for programming, to name a few.

I’ve read extensively about the mysterious world that is the Forex market. Here are a few write-ups that I recommend for programmers and enthusiastic readers:

This article was originally published in Toptal

Views: 2834

Tags: data

Comment

You need to be a member of Data Science Central to add comments!

Join Data Science Central

Videos

  • Add Videos
  • View All

© 2019   Data Science Central ®   Powered by

Badges  |  Report an Issue  |  Privacy Policy  |  Terms of Service