| / | Articles |
Articles
Trading
Automated Choice of Brokerage Company for an Efficient Operation of Expert Advisors
To post a new article, please log in or register
|
Automated Choice of Brokerage Company for an Efficient Operation of Expert Advisors [ ru ]IntroductionVery often we face situations when an Expert Advisor successfully operates with one brokerage company and is not profitable or even lossmaking on the other one. The reasons may be different. Different brokerage companies have different settings:
StatisticOf course we can start several terminals from different brokerage companies, use them a month or two and then choose one, with which the profit is maximal. But such testing is low-informative. It would be better to get more information: mean slippage per a trade, number of requotes that take place at opening of each certain trade, opening time and so on. In order not to have to analyze logs, a project Statistic was developed. It is based on the following set of rules:
Analyzing the statistic (number of requotes, time of a trade execution, slippage) and viewing all trades we can conclude, with what brokerage company it is better to work. If statistic on all companies is negative, we should change some EA parameters, for example, time in the market, frequency of trades. And change them until the EA starts working with a profit. If on a certain stage an EA stops bringing profit with one brokerage company being profitable on others, we stop testing this company. TheoryWe can organize submission of data from an EA into an application ether through files, or through dll. The variant with files is easier in terms of technical realization, because it does not require serious system programming. However, it is not very convenient to work with files, because we do not know beforehand where MetaTrader 4 terminals for different brokerage companies will be, on what currencies they will be tested, what to do if the files are lost, and so on. If we need everything to be done dynamically, with maximum security, it is better to organize data passing through dll.
![]()
PracticeExpert AdvisorCertainly, data about the current trade should be formed by an Expert Advisor. For data passing we need to form the interface of the function dll. For the implemented task we need three functions: bool NewExpert(string isBrokerName, string isInstrument, int Digit); Create a new Expert Advisor, identifying it by a broker's name and security. For the calculation of some statistical characteristics we pass the number of figures after a point in a security price. bool NewDeal(string isInstrument, int Action, int magik, double PriceOpen, int Slippage, int TimeForOpen, int Requotes); The registration of a new trade is performed the following way. While the terminal-process is already identified by a broker's name, for a new trade the name of a security upon which the trade is executed is enough. Other parameters are the trade characteristics. Table 1. Trade Opening
bool CloseDeal(string isInstrument, int magik, double PriceClose, int Slippage, int TimeForClose, int Requotes); A trade closing is identified upon a security and the magic. Passed parameters: Table 2. Trade Closing
Due to this interface, initialization and opening and closing functions will look like this:
int init() { int Digit; if(IsDllsAllowed() == false) { Print("Calling from libraries (DLL) is impossible." + " EA cannot be executed."); return(0); } if(!IsTradeAllowed()) { Print("Trade is not permitted!"); return(0); } Digit = MarketInfo(Symbol(), MODE_DIGITS); if((Digit > 0) && (Bid > 0)) { if(!NewExpert(AccountServer(), Symbol(), Digit)) { Print("Creation of a new broker failed"); return (0); } Print("A broker is successfully created "); return(0); } Print("No symbol in MarketInfo!"); return(0); } During the initialization after checking the terminal parameters (trade permission
and confirmation of DLL calling) we receive the information about a security's
digits and its current price. If both parameters are more than zero, the security
is adequately presented in the terminal and we can work with it. Each broker differs
in its name that can be received using the function AccountServer(), upon this
name terminals differ from one another in the shared memory. EAs differ in the
name of security they are trading with. That is why if different EAs are attached
to one and the same currency pair, they will download one and the same DLL copy
which may lead to collision. Function of opening a new order: int Deal(int act, double Lot) { int N = 0; int ticket; int err; double Price_open; double Real_price; datetime begin_deal; double Lots; int cmd; int magik; magik = GenericMagik() + 1; Lots = NormalizeDouble(Lot, 1); // checking margin for a position opening AccountFreeMarginCheck(Symbol(), cmd, Lots); err = GetLastError(); if(err > 0) { Print("No money for new position"); return(0); } begin_deal=TimeCurrent(); while(N < count) { if(act == 1) { Price_open = NormalizeDouble(Ask, Digits); cmd = OP_BUY; } if(act == 2) { Price_open = NormalizeDouble(Bid, Digits); cmd = OP_SELL; } ticket = OrderSend(Symbol(), cmd, Lots, Price_open, slippage, 0, 0, 0, magik); if(ticket > 0) { if(OrderSelect(ticket, SELECT_BY_TICKET) == true) { Real_price = OrderOpenPrice(); NewDeal(Symbol(), cmd,magik, Real_price , MathAbs(Real_price - Price_open), (TimeCurrent() - begin_deal), N); } return(ticket); } N++; Sleep(5000); RefreshRates(); } return(0); } An order is opened by the function Deal with two parameters: action (1 - buy, 2 - sell ) and lot. Each order differs from the previous one in magic - it is incremented. A position tries to open in count attempts. Thу information about the number of attempts together with opening duration, price and slippage is passed into a shared memory, from where it is read by the monitor.
bool CloseOrder(int magik) { int ticket, i; double Price_close; int count = 0; datetime begin_time; double Real_close; begin_time = TimeCurrent(); for(i = OrdersTotal() - 1; i >= 0; i--) { if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) if(OrderSymbol() == Symbol()) if(OrderMagicNumber() == magik) { while(count < 10) { if(OrderType() == OP_BUY) Price_close = NormalizeDouble(Bid, Digits); if(OrderType() == OP_SELL) Price_close = NormalizeDouble(Ask, Digits); if(OrderClose(OrderTicket(), OrderLots(), Price_close, slippage)) { Real_close = OrderClosePrice(); CloseDeal(Symbol(), magik, Real_close, MathAbs(Real_close - Price_close), (TimeCurrent() - begin_time), count); return(true); } count++; Sleep(5000); RefreshRates(); } } } return(false); } Function of closing CloseOrder() has only one input parameter - the magic. An order
tries to close several times and this number of attempts will be passed together
with the time of transaction execution, closing price and slippage into the memory
and then read by the monitor. The remaining code is the tested EA. So for using Statistic in your own EAs, you
need to import the necessary dll functions; for initialization and opening/closing
positions use functions Deal and CloseOrder. If you want, you may rewrite these functions, but data on transactions should
be passed in accordance with the interface contained in dll.
// Enable dll for operation with monitor #import "statistik.dll" bool NewExpert(string isBrokerName, string isInstrument, int Digit); // Create a broker bool NewDeal(string isInstrument, int Action, int magik, double PriceOpen, int Slippage, int TimeForOpen, int Requotes); bool CloseDeal(string isInstrument, int magik, double PriceClose, int Slippage, int TimeForClose, int Requotes); #import //---- extern int Num_Deals = 3; extern int TimeInMarket = 4; // maximally acceptable slippage int slippage = 10; // time for rest after a trade int TimeForSleep = 10; // period of request int time_for_action = 1; // number of attempts for opening a position int count = 5; // Function of a new bar bool isNewBar() { static datetime BarTime; bool res = false; if(BarTime != Time[0]) { BarTime = Time[0]; res = true; } return(res); } //+------------------------------------------------------------------+ //| Generation of magic | //+------------------------------------------------------------------+ int GenericMagic() { int deals; //---- for(int i = OrdersTotal() - 1; i >= 0; i--) { if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) if(OrderSymbol() == Symbol()) if(OrderMagicNumber() != 0) deals++; } return (deals); } //+------------------------------------------------------------------+ //| forming signals to open/close a position | //+------------------------------------------------------------------+ int GetAction(int &action, double &lot, int &magic) { int cnt, total; if(OrdersTotal() <= Num_Deals) { if(Close[1] > Close[2]) { action = 1; lot = 1; return(0); } if(Close[2] < Close[1]) { action = 2; lot = 1; return(0); } } total = OrdersTotal(); for(cnt = total - 1; cnt >= 0; cnt--) { if(OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES)) if(OrderSymbol() == Symbol()) if((TimeCurrent() - OrderOpenTime()) > TimeInMarket*60) { action = 3; magic = OrderMagicNumber(); return(0); } } } //+------------------------------------------------------------------+ //| expert start function | //+------------------------------------------------------------------+ int start() { int action = 0; double lot = 1; int magic = 0; while(!IsStopped()) { Sleep(time_for_action*1000); RefreshRates(); if(isNewBar()) { GetAction(action, lot, magic); if(((action == 1) || (action == 2))) { if(IsTradeAllowed()) Deal(action, lot); Sleep(TimeForSleep*1000); } if(action == 3) { if(IsTradeAllowed()) if(!CloseOrder(magik)) { Print("MANUAL CLOSING OF A POSITION IS NEEDED"); Sleep(TimeForSleep*1000); } } action = 0; lot = 0; magik = 0; } } Print("A serious error occurred, the EA stopped operating"); return(0); } //+------------------------------------------------------------------+The EA's executive block is an infinite cycle on the start function. At a preset frequency time_for_action the EA calls the analytical function GetAction() , which by reference returns an action that should be done by the EA, lot with which a position should be opened, and magic in case if you need to close a position. The analytical block is elementary here - buy, if the previous bar was more than the one before it, and sell if vice versa. Positions are closed by time. For testing your own EAs simply rewrite this block in accordance with their algorithm. You may make no changes in the executive part. DLLDLL may be implemented in different environments and in different languages. The
dll necessary for our work was created in Visual C++. The trades will have the
following structure: struct DealRec { int Index; int Magic; int Cur; int Broker; double PriceOpen; double PriceClose; int SlipOpen; int SlipClose; int Action; // 0 = BUY 1 = SELL int TimeForOpen; int TimeForClose; int ReqOpen; int ReqClose; int Profit; bool Checked; // indication that the position is closed };
They will be fulfilled in two stages - at opening and closing. I.e. one part of
data (opening price, slippage at opening etc.) is passed at opening, another part
(closing price, closing time etc.) is passed at closing. Prototypes of calling
a function in dll __declspec(dllexport) bool __stdcall NewExpert (char *isBrokerName, char *isInstrument, int Digit); __declspec(dllexport) bool __stdcall NewDeal (char *isInstrument, int Action, int magic, double PriceOpen, int Slippage, int TimeForOpen, int Requotes); __declspec(dllexport) bool __stdcall CloseDeal (char *isInstrument, int magic, double PriceClose, int Slippage, int TimeForClose, int Requotes);
MonitorAn optimal tool for a quick writing of applications with tables and graphical interface
- solution from Borland. That is Delphi and C++Builder. Monitor functions: create a shared memory, read data from it and display in tables, keep the statistics of slippage. There are some more options that make the work more convenient. So this is the functional of the monitor:
The implementation is in the attached zip-file Statistic Monitor.zip. For the project recompiling use the program C++Builder. Extension of the project file is *.bpr. The main code
is in в main.cpp. TestingFor testing a special EA was created - it has the simplest conditions of entering
and closing positions by time (the implementation was shown earlier). The EA with
dll and monitor.exe is in the zip-file monitor+dll+expert.zip. When starting, click START, thus creating a shared memory. DLL should be in the
folder system32. After that start several terminals and attach the EA to charts
of currencies, on which it is going to trade. After a number of trades statistics
is accumulated. The data is collected in the monitor/Journal. From time to time
they should be transfered into a file, stored in the form of html-page.
ConclusionEnabling dll in MQL4 allows to develop different application programs, which help
not only make decisions about trading, but also collect statistics. The latter
one may be very useful in trafing and in choosing a brokerage company. The created
application should help developers in this difficult search. For analyzing brokers,
attach statistic.dll to an Expert Advisor as described in the example analyzed
in this article. The files necessary for the work are in monitor+dll+expert.zip. For the operation copy statistic.dll into the folder system32, start Statistic.
exe from any location and open terminal with Expert Advisors, which download dll,
start trading and passing their data into the shared memory. Statistic.exe creates
auxiliary files, that is why it is better to start the application from an empty
folder. If the program is interesting to the developers of trading robots, it can
be modified and amended. It should be noted that not all brokerage companies provide similar conditions for the automated trading:
That is why it is strongly recommended to read carefully the regulations of the brokerage company you are going to work with.
Translated from Russian by MetaQuotes Software Corp.
Original article: http://articles.mql4.com/ru/367
Attachments:
Warning:
All rights to these materials are reserved by MetaQuotes Software Corp.
Copying or reprinting of these materials in whole or in part is prohibited.
Write to sharedmemory from multe DLL attached multi MT, and read to moniter exe program. In NewDeal(....) before write, check if((index = FindDeal(-1, -1, -1)) == -1) If last one some DLLwrited is not readed out, then no -1,-1,-1 item, then no write this newDeal, so this newDeal write faile FALSE, but also return true. Then How to sure multe DLL writing succeed ?
2009.06.28 08:52 DxdCn
2 comments
|