Algorithmic trading for dummies – part 2

stop-loss
Submit to StumbleUpon

Hi and welcome back to my blog!

This is a follow up to my previous article which introduced some of the basic concepts in trading and how they related to MetaTrader 4, which I’ll be using in this series of posts. Here is a link to the previous article if you’ve not read it already.

I’ll be walking through the creation of a basic trading algorithm from the initial stages of development, from being highly unprofitable, through to one producing nearly 100% return on investment over the course of 1 simulated year.

Recap

In the last article we finished up by creating a ‘hello world’ program in MQL4. In this one I want to introduce the trading functions, but first of all we should create some general helper functions which will aid our programming and debugging.

Helpers

MT4 (or MT5, for that matter) has no debugger in the strategy tester, which makes our lives that little bit more difficult as programmers. It means we have to resort to using the Print() function a lot when trying to determine the cause of a problem; this is unavoidable.

Asserts

However, one thing we can do is to use Asserts; borrowed from conventional programming, an Assert is a piece of code which will check the validity of a given statement and then halt the program and print a message if that statement is false.

Here is an example:

int error = OrderReliableLastErr();
Assert(error == 0, "BuyAtMarketPrice(): error, server returned error code " + error);

In this example, the assert is checking that the function OrderReliableLastErr() returned 0, i.e. there was no error. If there were an error (in this case, a non-zero return value), the program would halt and the message would be displayed in the Journal for us to inspect.

Here is the implementation for Assert in MQL4:

/*
	Check the given condition and stop execution if not met, outputting the given error
*/
void Assert(bool condition, string msg)
{
	if (!condition)
	{
		Print("ASSERT FAIL! " + msg);
		Comment("Fatal error occured! Please check journal");
		gError = true;
	}
}

You’ll notice that not only is the message Print()ed, but also a warning is displayed on screen using the Comment() function of MQL4; this alerts the user more clearly to the problem.

An assert should be used to detect completely invalid and unexpected behaviour and not just for all errors because the program cannot continue operation after an assert has fired.

One caveat of this method is it’s reliance on the global variable gError. gError is used so that the main part of the program which runs every tick can detect the firing of the assert and stop any further operation. In an ideal world, the assert would simply stop the strategy tester, but unfortunately there is no way to do this from code.

bool gError = false;
 
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
{
	//----
	if (!gError)
	{
		// normal operation
		...
	}
}

Once per bar

Recall that in MT4 the price-series data in the chart is divided up into bars which are spaced at regular intervals. In our programs it is often beneficial to be able to tell when the start of a bar occurs, because MT4 will call our start() function for every single tick and there might be 10s, 100s or 1000s of ticks per bar depending on the chosen time-frame.

Unfortunately the only way to do this reliably both in the strategy tester and during live testing is to use another global variable:

]
datetime gOldTime=0;
 
/*
*/
bool NewBar()
{
	bool new = Time[0] != gOldTime;
	gOldTime = Time[0];
	return (new);
}
 
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
{
	//----
	if (!gError)
	{
		if (NewBar())
		{
			// normal operation
			...
		}
	}
}

This function must only be called once per update, as each call modifies the global variable so successive calls made after the first during one update will return false incorrectly. Nevertheless, this is still a very useful function when used correctly.

Equality of prices vs floating point

When specifying prices to the MT4 API, one has to take into consideration the broker’s supported number of decimal places. For example, with a 5 digit broker it is unacceptable to submit 1.213201 as a price because there are too many decimal places. MT4 will throw a runtime error. What’s required is to use the function NormaliseDouble() on any prices you submit which are not from a MQL4 built-in variable, such as Ask or Bid.

Furthermore, when comparing two different prices it pays to use a function like this:

/*
	Are the two specified prices equal in the broker's eyes?
*/
bool PricesEqual(double a, double b)
{
	return (NormalizeDouble(a-b, Digits) == 0);
}

This helps rule out problems with prices being un-equal when compared using a floating point comparison, but being equal after being ‘normalised’.

Example forex broker (Affiliated)

Access to MT4 data

MT4 provides access to it’s data and functions via MQL4, here is a quick summary:

Time-series

Open, High, Low, Close, Volume and Time price-series data are all available to access in MT4 as global arrays.

Note: the use of the word global here refers to the scope of accessibility. MT4 has special variables which the documentation refers to as global variables, which are used to hold data between invocations of MT4.

They are indexed by bar, with 0 being the most recent bar.

Current Bid and Ask prices are also available as global variables, but only the most recent values.

For a full list of global MQL4 variables, please check the reference documentation here.

Indicators

MQL4 also provides full access to all the built-in indicators and also access to any custom ones. Here is an example of getting the value of a moving average:

// double iMA(	string symbol, int timeframe, int period, int ma_shift, int ma_method, int applied_price, int shift)
double ma = iMA(Symbol(), 0, 14, 0, MODE_SMA, PRICE_OPEN, 0);

This one line call evaluates the moving average indicator for:

  • The current symbol (i.e. the asset which the EA is running on, such as EURUSD)
  • The current time-frame (the time-frame the EA is running on, such as M1, M5 etc)
  • Using a period of 14 bars
  • With no visual offset (where the curve is actually drawn in the strategy tester, shifted into the past or future by a number of bars)
  • Using simple moving average in the calculations
  • Working on Open prices only
  • Using the current bar (bar 0) in the calculations.

Here is the documentation for the moving average indicator.

The documentation not only provides information about how to call these indicators, it also provides a very useful technical analysis of how they work and why you’d want to use them.

Actual trading functions – basic terminology

Before we can move on into the actual trading functions, we must cover the trading terminology which you will encounter almost right away when trying to trade, either by writing a program or manually in the MT4 interface.

Slippage

Due to the fact that your broker is probably located far away from you, actual trading operations are performed by sending a request over the internet. This request takes some amount of time to arrive at the broker and this delay can have consequences when considering orders placed for instant execution, such as market orders.

When submitting a market order to buy, for example you will always be buying at the current Ask price. However, what that current Ask price is at your broker may be different from the one you’ve got in MT4 running on your local machine. The slippage parameter allows you to mitigate this potential difference by permitting the actual buying price to be different by some number of points.

Of point of interest here is that slippage is something which could easily be manipulated by an unscrupulous broker in order to increase their profits by giving you an unfavourable price. Look for reviews of brokers which talk about the amount of slippage customers are experiencing when choosing a broker.

Simply setting this to zero will work in the strategy tester, but when it comes to live testing it may result in ‘requote’ errors.

Stop-loss

When you enter a trade, you expect the market to move in your favour before you can then close the trade in profit (either manually, or by using take-profit). However, if the market doesn’t move in your favour, stop-loss allows you to control the maximum amount you can lose in each trade. It is specified as a simple price.

In the above example a buy was made at 1.37657 with a stop-loss set at 1.36654 and price is currently at 1.37317 heading down towards the stop-loss.

You might argue that Stop-losses are unnecessary because you can close the trade manually, which is true except for the case of interrupted connection to your broker, like a power-cut – you need some level of protection to prevent unbounded losses.

For buy orders, stop-loss must be positioned below the buying price and for sell orders above the selling price (at a distance of some broker-specific number of points).

Setting a stop loss correctly is a tricky process – the closer you set it to the price, the higher the probability it will be hit, but the further away you put it the more you can potentially lose if your accuracy is insufficient.

Take-profit

In order to close a trade in profit, the alternative to manual closing (and useful for the same reasons as the stop-loss is) is to use take-profit. Take-profit works exactly like stop-loss; it’s specified as a simple price and represents the amount of profit you’d be happy to accept for a given trade.

For buy orders, take-profit must be positioned above the buying price and for sell orders below the selling price (at a distance of some broker-specific number of points).

In the above example a sell was made at 1.34720 with a take-profit at 1.34232 and price is currently at 1.34572 heading down towards the take-profit.

Stop-levels

In the take-profit and stop-loss definitions, you’ll notice that I mentioned there is a broker-defined minimum distance at which both take-profit and stop-loss must be set – this is called the stop-level and is defined in Points. It is actually a limitation placed on all pending orders (orders destined for the order-book). Take-profit and stop-loss are actually just pending-orders which are created and closed automatically by your broker.

You can find the stop-level like this:

/*
	Buy at the current market price
*/
int BuyAtMarketPrice(double lotSize, double slippage, double sl=0, double tp=0, string comment="", bool ecn=false, string symbol="")
{
        // find the broker's stop level
	int stopPoints = MarketInfo(Symbol(), MODE_STOPLEVEL);
 
        // convert to a price
        double stopPrice = stopPoints*Point;
 
        // make sure the stop loss and take profit are positioned correctly
	Assert(NormalizeDouble(Bid - sl, Digits) >= stopPrice  || sl == 0, "BuyAtMarketPrice(): stop loss too close to price");
	Assert(NormalizeDouble(tp - Bid, Digits) >= stopPrice || tp == 0, "BuyAtMarketPrice(): take profit too close to price");
 
        ...
}

There is also a further restriction on all pending orders, that they may not be placed ‘inside’ the current spread. So even if your broker has a stop-level of 0, you still cannot place any pending orders (including take-profit and stop-loss) anywhere between the Ask and Bid prices.

The full set of rules regarding orders and stop-levels is given in the following documentation:

Requirements and Limitations in Making Trades

Lot-size

In forex, trading volume is specified in fractional units called a lot. One standard lot is usually 100,000 base currency units (for example in USDJPY that would be $100,000) although this is a broker specific quantity. You can determine your broker’s lot-size like this:

double lotSize = MarketInfo(Symbol(), MODE_LOTSIZE);

Since most people don’t have $100,000 lying around with which to trade, luckily you can specify fractional lot sizes. The lowest allowed by your broker can be determined like this:

double minLotSize = MarketInfo(Symbol(), MODE_MINLOT);

Leverage

For some reason MT4 has a minimum specifiable lot size of 0.01 (regardless of a broker’s own minimum), which equates to $1000. Again, $1000 per trade seems like it might be out of the reach of most people in the world and far too risky in the first place. The reason for the huge lot-size is historical; retail forex trading is only a fairly recent development, it used to be that only banks and huge financial institutions could trade and they were only interested in moving huge amounts of money.

Using leverage is the only way you can really trade in retail forex, unless you are very rich. Leverage is a bit like a loan; the broker takes your initial deposit as payment (say $1000), and if their leverage is 1:100 would allow you to trade in units of up to $100,000, or one standard lot. Now, this seems extremely risky because you could potentially then lose more than you actually deposited. This is where the choice of broker becomes extremely important – it is perfectly possible for a broker to prevent you from losing more than you deposited (by initiating a margin-call and auto-closing your orders if they are losing sufficiently) and indeed, some brokers will do that (Oanda, for instance). But of course, some will not so it really pays to read the terms and conditions.

Here is a great description of how leverage works from babypips.com.

Margin-call

A margin-call used to mean a guy on the end of a phone telling you that all your deals were bad and about to cost you a lot of money. Now it’s completely automated – if you’ve made a bad deal and your open trades lose more than a certain amount your broker will auto-close your trades to prevent unbounded loss. This is called a margin-call. As I mentioned above it’s very important to chose a broker who will prevent you losing more than your initial deposit.

Another babypips.com definition is here

Actual trading functions

Ok, lets cover the way you actually perform trading operations in MQL4.

MQL4 provides access to a whole host of different trading functions which you can see all of here: MQL4 Trading functions. I’m going to introduce the most simple two functions: market orders buy, sell and close.

OrderSend() and OrderClose() provide access to this functionality.

OrderSend

At first, the OrderSend function seems quite daunting, with 11 separate parameters to pass. In reality it’s actually quite simple though, thankfully!

Here is the prototype:

int OrderSend(	string symbol, int cmd, double volume, double price, int slippage, double stoploss, double takeprofit, string comment=NULL, int magic=0, datetime expiration=0, color arrow_color=CLR_NONE)

Lets run through the parameters.

  • symbol – The symbol to trade, use Symbol() for the current one
  • cmd – The actual type of trade to make, here is a full list
  • volume – The lot-size of the trade, in fractional lots
  • price - The price at which to trade, for market orders this must be Bid or Ask depending on the type of order
  • slippage – The number of points of slippage to accept from your broker
  • stoploss – The price at which to set the stop-loss, can be 0 for no stop-loss
  • takeprofit – The price at which to set the take-profit, can be 0 for no take-profit
  • comment – (optional), a comment to place on the order which will be visible when hovering over the order in the MT4 interface
  • magic – (optional), a magic number is something which allows an EA to uniquely distinguish its own orders for any manually placed orders, or orders from other EAs running on the same account
  • expiration (optional), an expiration time for pending orders – this is not supported by some brokers
  • arrow_color (optional), the colour which the trades will appear in the MT4 interface

Placing a buy/sell market order

Here is an example of placing a buy-order, with no take-profit or stop-loss for 0.1 lots and accepting 0 points of slippage:

int buyTicket = OrderSend(Symbol(), OP_BUY, 0.1, Ask, 0, 0, 0);
Assert(buyTicket != -1, "Fatal error sending buy order!");

An example of a sell-order:

int sellTicket = OrderSend(Symbol(), OP_SELL, 0.1, Bid, 0, 0, 0);
Assert(sellTicket!= -1, "Fatal error sending sell order!");

As you can see, the OrderSend() function returns a ticket which uniquely identifies the trade, or -1 for failure. This ticket is useful for when we need to close the trade, or for identifying if the trade is in profit or loss.

Closing a buy/sell market order

Closing an order is done using the OrderClose() function. Here is the prototype:

bool OrderClose(int ticket, double lots, double price, int slippage, color Color=CLR_NONE)

Lets run through the parameters:

  • ticket – Ticket number of the order, returned by the OrderSend() function
  • lots – Fractional number of lots to close in this order (it is possible to close less volume than you initially ordered, this is called a partial close)
  • price – Price at which to close the order, for market orders this must be Bid or Ask depending on the type
  • slippage – The amount of slippage to accept from the broker
  • Color – The colour for the closing arrow drawn on the chart in MT4

It is worth explaining how closing an order works behind the scenes to understand why the slippage parameter is necessary. When an order is closed, the broker enters an order into the market of the opposite type to which was initially opened. Recall back to the last article where I explained that in forex, every buy must be closed with a sell? This is the implementation of that fact. And because of this, we must suffer the dreaded slippage of the broker once again.

Here is an example of the usage of OrderClose():

bool success = OrderClose(buyTicket, 0.1, Bid, 0);
Assert(success, "Fatal error closing buy order");

And similarly for a sell order:

bool success = OrderClose(sellTicket, 0.1, Ask, 0);
Assert(success, "Fatal error closing sell order");

Our first trading algorithm

Ok, so now we actually have learned everything we need to create the most basic trading algorithm (EA in MT4 terminology).

Buying and selling at random

The trading methodology will be to simply buy and sell at random, wait a random amount of time and then close the order. There will be a maximum of one order opened at any one time and the maximum amount of time to wait before closing will be specified as a user parameter.

Here is the realised EA:

//+------------------------------------------------------------------+
//|                                              BuySellAtRandom.mq4 |
//|                                                    Wildbunny Ltd |
//|                                      http://wildbunny.co.uk/blog |
//+------------------------------------------------------------------+
#property copyright "Wildbunny Ltd"
#property link      "http://wildbunny.co.uk/blog"
 
//--- input parameters
extern int       OrderCloseMaxMinutes=2000;
 
bool gError=false;
datetime gOldTime=0;
 
/*
	Check the given condition and stop execution if not met, outputting the given error
*/
void Assert(bool condition, string msg)
{
	if (!condition)
	{
		Print("ASSERT FAIL! " + msg, true);
		Comment("Fatal error occured! Please check journal");
		gError = true;
	}
}
 
/*
*/
bool NewBar()
{
	bool new = Time[0] != gOldTime;
	gOldTime = Time[0];
	return (new);
}
 
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
{
	//----
 
	//----
	return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
{
	//----
 
	//----
	return(0);
}
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
{
	//----
	if (!gError && NewBar())
	{
		if (OrdersTotal() == 0)
		{
			int ticket;
 
			if (MathRand()%2 == 0)
			{
				ticket = OrderSend(Symbol(), OP_BUY, 0.1, Ask, 0, 0, 0);
				Assert(ticket != -1, "Failed sending buy order!");
			}
			else
			{
				ticket = OrderSend(Symbol(), OP_SELL, 0.1, Bid, 0, 0, 0);
				Assert(ticket != -1, "Failed sending sell order!");
			}
		}
		else if (OrderSelect(OrdersTotal()-1, SELECT_BY_POS))
		{
			int minutesSinceOrder = (Time[0] - OrderOpenTime()) / 60;
			int randomMinutes = MathRand() % OrderCloseMaxMinutes;
 
			if (minutesSinceOrder > randomMinutes)
			{
				bool success = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 0);
				Assert(success, "Failed closing order!");
			}
		}
	}
 
	//----
	return(0);
}
//+------------------------------------------------------------------+

Compile the EA, and then set the following settings in the strategy tester:

  • Time-frame H1
  • For the period 2011-2012
  • Initial deposit of 2000

Hit start and then you should be presented with a report similar to this:

It contains very important information such as total profit/loss, draw-down, number of trades etc. Lets run through what they mean:

  • Bars in test – the number of bars in the chosen time-frame, in the above case hour bars
  • Mismatched chart errors – any errors which occurred due to bad back-test data
  • Initial deposit – the initial simulated deposit
  • Total net profit – the net profit of the simulation
  • Profit factor – the ratio between gross profit and loss, 1:1 would be 1.0, higher numbers indicate profitability and the higher the better
  • Absolute drawdown – the maximum amount which the initial balance was reduced by, the lower the better
  • Total trades – total number of trades performed
  • Ticks modelled – the number of calls to your start() function
  • Modelling quality – an estimate of the reliability of the simulation, very important – more on this in a later article
  • Gross profit/loss – the gross profit/loss of the simulation
  • Expected payoff – the average profit/loss factor for one individual trade
  • Maximal drawdown – the largest difference in the profit graph from the highest peak to the lowest trough, the lower the better
  • Relative drawdown – the draw down percentage in relation to the account balance at the time, the lower the better
  • Short/long positions won – the percentage of sells/buys which resulted in profit, the higher the better
  • Profit trades – the percentage of all trades which resulted in profit, the higher the better
  • Largest profit/loss trade – largest single profit/loss trade
  • Average profit/loss trade – the average over all profit/loss trades
  • Maximum consecutive wins/losses – number of consecutive trades which were profitable/lossy
  • Maximal consecutive profit/loss – the maximal amount of consecutive profit/loss over all trades
  • Consecutive wins/losses – the actual number of consecutive trades which were profitable/lossy

Most important parts in the report

The most important parts of the report are the net profit, the draw-down and the average profit/loss. Net profit should obviously be higher than 0, preferably a lot higher, while relative draw-down should be as close to zero as possible.

Analysing the inherent risk is an extremely important factor for any investor and each EA is a potential investment opportunity. One way to calculate risk is to look at the average profit/loss ratio in the report.

In the above example the risk/reward ratio is 1.05:1, calculated as:

risk reward = average loss / average profit

This risk/reward ratio is quite good in general as we don’t risk much more than we can earn for each individual trade. However, this is not the full story of course. What is also necessary to consider is the profit factor, which in this case is less than 1, indicating an unprofitable system. So we have a low risk (on a trade by trade basis) unprofitable system, with very high draw-down!

So in summary, this EA is low profit and high-risk (because of the huge draw-down) – the worst of both worlds!

Analysis

Lets explore the results of this EA. Trading at random should result in an EA which is break-even if it wasn’t for one important factor: the spread. Every time a trade is made (opened and then closed) we have to pay the cost of the spread to the broker. The higher the number of trades, the more spreads you will have to pay.

An example of paying the spread; equal movements in price result in only break-even in one direction and increased loss in the other

This is visible in the following example if we increase the number of trades by waiting only 1 bar before closing each trade:

In fact, the account value went to zero in much less than 1 year. In general, the fewer the number of trades were used to reach a given profit, the more efficient the EA since the amount of spread paid will be less.

Improvements

What if we change the EA to attempt to lock in profits once they occur? Looking at the original report, the average profit is $36.08 so what if we add some code to create a stop-loss at break-even (the order open price) once the profit reaches this level in any order?

Stop loss to break-even

Ok, so an improvement was made – the EA is now in profit by $392 and the draw-down has decreased to 65%. A couple of interesting points to note are the way the average winning percentage has changed along with the average loss per trade. The EA now wins 54% of the time (compared to 51%) and the risk reward ratio has changed to 1.14:1 because the average profit trade decreased to $33.01.

By moving the stop-loss to break-even once we are in profit, the chances of the trade being a winner naturally increase, but the average amount won will decrease because there is more likelihood that the stop-loss will be triggered before the profit could rise back up to the level it might have otherwise had with the original method of closing trades.

This is an important point to understand in general: the closer a stop-loss is to the current price, the more likely it is to be hit.

Partial close at average profit

Ok, so what if we also close half of the order when we reach the average profit level? Recall that it is possible to close a smaller fraction of lots than were initially opened in the order.

A big improvement – now we have nearly 100% profit (compared to the initial investment) and the draw-down has reduced to 44%. However, the risk-reward ratio is now 1.58:1 but the average winning percentage is up to 64%.

The partial close allows 50% of the original order to behave as it would have in the previous version, while also taking an immediate profit. The effect of this is to increase the winning percentage since the closed portion of the order was winning and the existing portion will also be winning since it starts off in profit and has stop-loss at break-even. Higher winning percentage doesn’t always translate to higher profit – the average loss will likely increase to compensate since we’re taking less profit by closing half the order ‘early’ compared to the original algorithm.

At this stage we’re reaching the point where we’ve extracted as much as we could from the initial strategy. By opening the trades completely at random and only concentrating on how trades are closed we have seen how it is possible to tune an EA from an initially terrible result to a much better one.

However, it should be noted that it wouldn’t be wise to trade with this EA because of the high draw-down and the short testing period involved. Also the EA is paying a lot in the cost of spreads due to the high number of trades (approximately $2000 in total on spreads alone).

Next time

That’s all for this article!

In the next article I’m going to cover some of the different trading techniques (trailing-stop, grids, averaging, martingale etc) and the risks and benefit of each one.

If you’d like to show your appreciation for this article and help ensure I’m able to write more like this, you can purchase the source code for all the examples in this article; they come with full rights to use however you please even in commercial products. Please do not trade using these EAs however, they are for education purposes only!

USD 9.99

Cheers, Paul.

Submit to StumbleUpon

About Paul Firth

A games industry veteran of ten years, seven of which spent at Sony Computer Entertainment Europe, he has had key technical roles on triple-A titles like the Bafta Award Winning Little Big Planet (PSP), 24: The Game (PS2), special effects work on Heavenly Sword (PS3), some in-show graphics on the BBC’s version of Robot Wars, the TV show, as well as a few more obscure projects.   Now joint CEO of Wildbunny, he is able to give himself hiccups simply by coughing.   1NobNQ88UoYePFi5QbibuRJP3TtLhh65Jp
This entry was posted in Algorithmic trading, Finance and tagged , , , , , , . Bookmark the permalink.

15 Responses to Algorithmic trading for dummies – part 2

  1. Jon says:

    Very nice articles you are submitting
    Do you have any article on HFT intraday trading or some advice on that topic ?

    • Paul Firth says:

      Hi Jon,

      HFT at it’s most extreme requires a very fast trade execution speed which can really only be achieved by the big players using colocation – that side of things is out of reach of the retail trader who must settle for less frequency. Something to bare in mind is that the more trades you make, the more spreads you pay so it can be less efficient to trade more often (especially using market orders). Another factor which can hinder the HFT retail trader is the broker itself, which (if they decide you are using too much of their network bandwidth) can start lagging your connection to compensate.

      Hope that helps!

      Cheers, Paul.

  2. J says:

    I am running though this article using the (bought) source code examples and I’m wondering about how you are generating the informative strategy report screen shots you got in your article? I can get the same information by browsing though the tabs in the Strategy Tester but I would much rather have it all in one image/pdf for quick overview.

    Also, on another note.. I can’t get Oanda history data from before 2011.12.19 which is a bit odd/disconcerting to say the least..

    • Paul Firth says:

      Hi there,

      Just right click and save report, it will save a web-page which contains all the nice info :)

      Cheers, Paul.

      • J says:

        Thanks, it is these small things that really helps when getting started with new languages/environments! Also I’ve noticed that the “modelling quality” for the same historical period on Oanda seem to oscillate quite a bit which again affect Net Profit.. makes me wonder about acquiring higher quality data for testing against.

  3. QuantHFTer says:

    First, thank you for your nice concise tutorial. It was really helpful for someone just started learning to code like me. I waiting for your third part.

    Also, i have a suggestion that you can make the donation amount so small so this will encourage many to donate and support your wonderful articles.

  4. Andrew says:

    Hi
    Great article!
    Has MT4 the same function range as MT5? (Seems nobody is using mt5 ?)
    Seems v5 not compatible to 4
    can i use it for stocks + other (options,…) ?
    Is there a way to access the order book ?
    -> is there a known interface/possibility to add additional code or is it
    easier to use another traderSW?
    thanks Andrew

    • Paul Firth says:

      Hi Andrew,

      MT4/5 are both designed for retail forex trading rather than stocks; the reason being that in MT4/5 you can never actually own the thing you are buying or selling because it always gets converted back into the currency you started with. Obv with stocks and shares you actually need to own them after you buy them, so it’s not really suited for the purpose.

      I’m not sure what the alternative is actually… if you find one, let me know!

      Cheers, Paul.

  5. Kevin Rea says:

    I downloaded Metatrader but it appears that USDINR is not an option.
    Anyone know how to create algorithms to trade the rupee?

  6. Ardin says:

    Hi,

    Your article is an enlightenment. Thank you.
    I noticed that your modelling quality is 99.90%. It’s so great. Do you have it from Oanda or downloaded the tick data somewhere else? My broker tick data only provide me 25.00% modelling quality.

    • Paul Firth says:

      Hi Ardin,

      All MT4 brokers give you only 25% unfortunately. In order to get 99% you need to download it yourself – look into a free program called TickstoryLite. It’s quite an involved process, so read up on it well, but it pays off :)

      Cheers, Paul.

  7. Chris Crowe says:

    Thanks for the great write-up, I’ve learned a great deal from your two lessons and am getting to grips with the code. I’ve encountered a small bug which perhaps only occurs with newer releases. In your basic demo code, I had to change ‘new’ to something else, as MQ4 seems to think that ‘new’ is some sort of global variable, so won’t allow it as a name. I changed it to:

    bool anew = Time[0] != gOldTime;
    gOldTime = Time[0];
    return (anew);

    and it compiles without hiccup.

  8. Paddy says:

    I would like to bring your attention to a deviation from your code samples.

    When I create a new EA there is no ‘int Start()’ function in the blank template; however there is a ‘void onTick()’ function which appears to provide the functionality that you described.

    As it is now declared as void, it cannot return a value. Therefore the new code for the HelloWorld example had to be modified to:


    //+------------------------------------------------------------------+
    //| Expert tick function |
    //+------------------------------------------------------------------+
    void OnTick()
    {
    //---
    Print("Hello World");
    return;
    }
    //+------------------------------------------------------------------+

    Perhaps there has been some update on MQL4?

    Thank you for your posts on algo trading. They have really eased the learning curve for me!!

    Cheers

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

WP-SpamFree by Pole Position Marketing