Разработка сайта для Вашего бизнеса. Веб дизайн. Дизайн логотипа, фирменного стиля, рекламная фотография . Комплексный рекламный креатив.

Ralex. We do the work.
На рынке с 1999го года. Средняя ценовая категория. Ориентация на эффективность решений.
Ознакомтесь с нашим портфолио
Узнайте больше о услугах
Свяжитесь с нами:
E-mail: [email protected]
Tel: (044) 587 - 84 - 78
Custom web design & дизайн и разработка сайта "под ключ"
Креативный, эффективный дизайн. Система управления сайтом (СУС).
Custom flexible разработка систем электронной коммерции
Система e-commerce разрабатывается под индивидуальные потребности. Гибкая функциональность.
Search Engine Optimzation & оптимизация под поисковые системы (SEO)
Постоянная оптимизация и мониторинг сайта в поисковых системах. Достигаем результата быстро и эффективно
Custom logo design & дизайн логотипа и фирменного стиля
Многолетний опыт. Огромное портфолио. Уникальное предложение и цена.
профессиональная рекламная фотография
креативно, смело, качественно
Custom logo design & рекламный креатив. дизайн рекламы
Многолетний опыт. Огромное портфолио. Уникальное предложение и цена.

Використання MetaTrader 5 як постачальника торгових сигналів для MetaTrader 4

  1. Вступ
  2. 1. Як копіювати торгівлю учасників Automated Trading Championship?
  3. 2. Що копіювати - позиції, ордера або угоди?
  4. 3. Як надавати "сигнали"?
  5. 4. Відправлення торгових сигналів
  6. Висновки

Вступ

Наша взаимовыгодная связь https://banwar.org/

Для вивчення цього питання і написання статті у мене було кілька причин.

По-перше, хоча офіційний реліз платформи MetaTrader 5 відбувся досить давно, ми все ще чекаємо того моменту, коли наші брокери нададуть нам можливість торгувати на реальних рахунках. Деякі вже реалізували вдалі торгові стратегії на мові MQL5 і тепер хотіли б використовувати їх на реальних рахунках. Іншим, можливо, більше подобається організація торгівлі в MetaTrader 5, і вони хотіли б торгувати на ній вручну замість MetaTrader 4.

По-друге, протягом Automated Trading Championship у багатьох виникала думка про копіювання угод лідерів на реальні рахунки. Деякі створили свої власні способи копіювання угод, інші все в пошуку найкращих варіантах реалізації цієї ідеї (і способів управління капіталом) для отримання результатів, найбільш близьких до учасників Чемпіонату.

По-третє, у деяких трейдерів є хороші стратегії, і вони хотіли б надавати свої торгові сигнали. Їм потрібна можливість поширення торгових сигналів в реальному часі для декількох рахунків без втрати продуктивності.

Ці питання весь час цікавили мене, і зараз я спробую знайти рішення, яке задовольняє всім цим вимогам.

1. Як копіювати торгівлю учасників Automated Trading Championship?

Останнім часом на сайті MQL5.community я знайшов декілька статей, в яких мені вдалося розібратися і зрозуміти, що я здатний це реалізувати. Скажу також, що у мене була програма, за допомогою якої я торгував на реальному рахунку (на щастя, з прибутком), слідуючи за угодами учасників, які публікуються на сайті Чемпіонату. Проблема була в тому, що дані оновлюються кожні 5 хвилин і можна пропустити момент відкриття і закриття угод.

з форуму Чемпіонату я дізнався, що інші люди також використовують цей спосіб, проте він не є ефективним. Крім того, він створює величезне навантаження на сервер Чемпіонату і організаторам це може не сподобатися. Чи є рішення? Я подивився всі варіанти і мені сподобалася можливість доступу по паролю інвестора (при якому торгівля заборонена) в MetaTrader 5 до рахунку будь-якого учасника Чемпіонату.

Чи можемо ми використовувати цей спосіб для отримання інформації про всієї торговельної активності і передавати її в реальному часі? Щоб з'ясувати це, я створив радника і спробував запустити його на рахунку, доступному лише за паролем інвестора. На мій подив, його вдалося запустити і виявилося можливим отримувати інформацію про позиції, ордерах і угодах - це були двері до можливого рішення!


2. Що копіювати - позиції, ордера або угоди?

Якщо нам доведеться передавати інформацію з MetaTrader 5 в MetaTrader 4, то нам буде потрібно врахувати всі типи ордерів, можливі в MetaTrader 4. Крім того, при проходженні за торгівлею ми хочемо знати про будь-які дії, що здійснюються на торговому рахунку. Порівняння статусу позицій (Positions) на кожному тику або кожну секунду не дасть нам повну інформацію.

З цієї причини краще слідувати за ордерами (Orders) або угодами (Deals).

Я став дивитися на структуру ордерів:

Ордери гарні з тієї причини, що вони виставляються до здійснення угоди, і також містять інформацію про те, чи є ордер відкладеним. Однак в ордерах не вистачає однієї важливої ​​речі, яка присутня в угодах - типі угоди ( ENUM_DEAL_ENTRY ):

Тип угоди DEAL_ENTRY_TYPE допомагає зрозуміти, що сталося з рахунком трейдера, в той час як робота з ордерами вимагає розрахунків. Краще було б спільно працювати з угодами і ордерами, це дало б нам можливість точно слідувати торгівлі у випадках, коли використовуються відкладені ордери. Оскільки характер руху цін у різних брокерів може бути різним, використання відкладених ордерів може привести до помилок і неправильних результатів.

У разі якщо ми слідуємо лише за угодами (Deals), ми як і раніше будемо виконувати ордера, але з невеликою затримкою, яка визначається мережевим з'єднанням. При виборі між швидкістю (відкладені ордери) і продуктивністю (угоди) я вибрав останнє.


3. Як надавати "сигнали"?

Способи з'єднання і передачі даних між терміналом MetaTrader і іншими додатки і комп'ютерами обговорювалися в різних статтях. Оскільки я хочу щоб інші клієнти мали можливість до нас приєднуватися (швидше за все, вони будуть робити це з інших комп'ютерів), я вибрав роботу через сокети по протоколу TCP.

Так як мова MQL5 не дозволяє працювати безпосередньо з функціями API, нам буде потрібно використовувати зовнішні бібліотеки. Існує безліч статей про використання бібліотеки "WinInet.dll" (наприклад, "Використання WinInet.dll для обміну даними між терміналами через Інтернет" і ін.), але жодна з них не задовольняє нашим вимогам.

Оскільки я трохи знайомий з мовою C # (до цього я зробив пару серверів, що працюють в режимі реального часу), я вирішив створити свою власну бібліотеку. Я скористався статтею "Як відкрити світ C # з MQL5 шляхом експорту некерованого коду" , Яка допомогла мені вирішити питання сумісності. Я написав сервер з дуже простим інтерфейсом і можливістю одночасного з'єднання з 500 клієнтами (для його роботи на вашому комп'ютері повинен бути встановлений .NET framework версія 3.5 або вище, на більшості комп'ютерів " Microsoft .NET Framework 3.5 вже встановлено).

#import "SocketServer.dll" string About (); int SendToAll (string msg); bool Stop (); bool StartListen (int port); string ReadLogLine (); #import

Сам по собі сервер працює в фоновому режимі в окремих потоках, тому робота терміналу або стратегії не сповільнюється і не блокується незалежно від кількості підключених клієнтських з'єднань.

Код на C # виглядає наступним чином:

internal static void WaitForClients () {if (server! = null) {Debug ( "Cant start lisening! Server not disposed."); return; } Try {IPEndPoint localEndPoint = new IPEndPoint (IPAddress.Any, iPort); server = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); server.Bind (localEndPoint); server.Listen (500); isServerClosed = false; isServerClosedOrClosing = false; while (! isServerClosedOrClosing) {allDone.Reset (); server.BeginAccept (new AsyncCallback (AcceptCallback), server); allDone.WaitOne (); }} Catch (ThreadAbortException) {} catch (Exception e) {Debug ( "WaitForClients () Error:" + e.Message); } Finally {if (server! = Null) {server.Close (); server = null; } IsServerClosed = true; isServerClosedOrClosing = true; }} Internal static void AcceptCallback (IAsyncResult ar) {try {allDone.Set (); if (isServerClosedOrClosing) return; Socket listener = (Socket) ar.AsyncState; Socket client = listener.EndAccept (ar); if (clients! = null) {lock (clients) {Array.Resize (ref clients, clients.Length + 1); clients [clients.Length - 1] .socket = client; clients [clients.Length - 1] .ip = client.RemoteEndPoint.ToString (); clients [clients.Length - 1] .alive = true; } Debug ( "Client connected:" + clients [clients.Length - 1] .ip); }} Catch (Exception ex) {Debug ( "AcceptCallback () Error:" + ex.Message); }}

Детальніше про роботу з асинхронними серверними сокетами C # можна прочитати в Microsoft MSDN або статтях, які можна знайти за допомогою Google .

4. Відправлення торгових сигналів

У терміналі MetaTrader 4 ми б хотіли отримувати інформацію весь час (не тільки при приході нового тика), тому для цієї мети замість радника ми використовуємо скрипт. Також нам потрібна можливість відкриття сокетного з'єднання з нашим постачальником торгових сигналів - терміналом MetaTrader 5.

Для цієї мети я скористався допомогою MQL4 codebase: " https://www.mql5.com/en/code/9296 ", Де є цілком хороша бібліотека ( WinSock.mqh ) Дозволяє дуже просто працювати з сокетами. Деякі висловлювали претензії по стабільності її роботи, проте для моїх цілей вона виявилася цілком достатньою, і в процесі тестування проблем у мене не було.

#include <winsock.mqh>


5. Обробка даних

Тепер, коли все ясно з принципом роботи, нам потрібно реалізувати відправку інформації про угоди всім клієнтам в форматі, який вони зможуть зрозуміти і обробити.

5.1. серверна частина

Як ми з'ясували, це буде радник, причому він не повинен бути прив'язаний до валютній парі робочого графіка.

При запуску він стартує прослуховує потік, який чекатиме вхідні з'єднання:

int OnInit () {string str = ""; Print (UTF8_to_ASCII (About ())); Print ( "Starting server on port", InpPort, "..."); if (! StartListen (InpPort)) {PrintLogs (); Print ( "OnInit () - FAILED"); return - 1; }

У цій реалізації радник не дбає про приєднаних клієнтів. При здійсненні кожної операції він буде відправляти повідомлення всім клієнтам, навіть якщо вони відсутні. Оскільки нам потрібна лише інформація про угоди, ми будемо працювати через функцію OnTrade () , А обробник OnTick () приберемо. У цій функції ми будемо переглядати історію торгівлі і в разі укладення угоди приймати рішення про відправку інформації.

Для кращого розуміння в коді є коментарі:

void OnTrade () {datetime dtStart = TimeCurrent () - 60 * 60 * 24; datetime dtEnd = TimeCurrent () + 60 * 60 * 24; if (HistorySelect (dtStart, dtEnd)) {for (int i = 0; i <HistoryDealsTotal (); i ++) {ulong ticket = HistoryDealGetTicket (i); if (HistoryDealGetInteger (ticket, DEAL_ENTRY)! = DEAL_ENTRY_STATE) {if (HistoryDealGetInteger (ticket, DEAL_TIME)> g_dtLastDealTime) {if (HistoryDealGetInteger (ticket, DEAL_ENTRY) == DEAL_ENTRY_OUT) {vUpdateEnabledSymbols (); } Else if (HistoryDealGetInteger (ticket, DEAL_ENTRY) == DEAL_ENTRY_INOUT) {vEnableSymbol (HistoryDealGetString (ticket, DEAL_SYMBOL)); } If (bIsThisSymbolEnabled (HistoryDealGetString (ticket, DEAL_SYMBOL))) {int cnt = SendToAll (sBuildDealString (ticket)); if (cnt <0) {Print ( "Failed to send new deals!"); } Else {g_dtLastDealTime = (datetime) HistoryDealGetInteger (ticket, DEAL_TIME); }} Else {g_dtLastDealTime = (datetime) HistoryDealGetInteger (ticket, DEAL_TIME); }}}}}}

Як ви вже зрозуміли, в разі знаходження нової угоди ми викликаємо функцію BuildDealString () для підготовки даних до відправки. Всі дані передаються в текстовому форматі, інформація про кожну угоди починається з символу '<' і закінчується символом '>'.

Це допоможе нам розділити рядки з декількома операціями, оскільки при передачі даних по протоколу TCP / IP пакети можуть склеюватися і в них може міститися інформація про декількох угодах.

string sBuildDealString (ulong ticket) {string deal = ""; double volume = 0; bool bFirstInOut = true; if (HistoryDealGetInteger (ticket, DEAL_ENTRY) == DEAL_ENTRY_INOUT) {if (PositionSelect (HistoryDealGetString (ticket, DEAL_SYMBOL))) {volume = PositionGetDouble (POSITION_VOLUME); } Else {Print ( "Failed to get volume!"); }} Else {volume = HistoryDealGetDouble (ticket, DEAL_VOLUME); } Int iDealEntry = (int) HistoryDealGetInteger (ticket, DEAL_ENTRY); if (iDealEntry == DEAL_ENTRY_OUT &&! PositionSelect (HistoryDealGetString (ticket, DEAL_SYMBOL))) {iDealEntry = DEAL_ENTRY_OUTALL; } StringConcatenate (deal, "<", AccountInfoInteger (ACCOUNT_LOGIN), ";", HistoryDealGetString (ticket, DEAL_SYMBOL), ";", Type2String ((ENUM_DEAL_TYPE) HistoryDealGetInteger (ticket, DEAL_TYPE)), ";", Entry2String (iDealEntry) , ";", DoubleToString (volume, 2), ";", DoubleToString (HistoryDealGetDouble (ticket, DEAL_PRICE), (int) SymbolInfoInteger (HistoryDealGetString (ticket, DEAL_SYMBOL), SYMBOL_DIGITS)), ">"); Print ( "DEAL:", deal); return deal; }

Можливо, ви здивовані появою нового типу угоди - DEAL_ENTRY_OUTALL. Цей тип створений мною, причину його появи ми побачимо при розгляді обробки обсягів торгівлі на стороні MetaTrader 4.

Інший цікавий момент - функція OnTimer () . При ініціалізації проводиться виклик функції EventSetTimer (1) для виклику таймера кожну секунду. У коді обробника таймера присутній лише один рядок, яка виводить інформацію в логи сервера:

void OnTimer () {PrintLogs (); }

Функцію PrintLogs () рекомендую викликати (для виведення інформації про статус і помилки) після виконання кожної функції серверної бібліотеки.

На стороні сервера ви також знайдете вхідний параметр StartupType:

enum ENUM_STARTUP_TYPE {STARTUP_TYPE_CLEAR, STARTUP_TYPE_CONTINUE}; input int InpPort = 2011 року; input ENUM_STARTUP_TYPE InpStartupType = STARTUP_TYPE_CONTINUE;

Цей параметр доданий через те, що радник-постачальник сигналів може бути надіслано на рахунок, на якому вже є відкриті позиції (наприклад, відкриті в ході Чемпіонату) і тому ця інформація для клієнтської сторони може вводити в оману. За допомогою цього параметра можна вибирати режим отримання інформації: існуючі відкриті позиції або тільки нові позиції.

Це також важливо для випадків, якщо ви вперше підключаєтеся до рахунку, на якому йде торгівля, або ж підключалися раніше, але перезапускати комп'ютер, програму або зробили модифікації вашого коду.

5.2. клієнтська частина

На стороні клієнта працює скрипт з нескінченним циклом, що містить функцію отримання даних від сокета recv. Оскільки ця функція не є блокує (до моменту отримання даних з сервера), істотною завантаження процесорного часу вона не виробляє.

/ --- запуск і початку збору і обробки даних while (! IsStopped ()) {Print ( "Client: Waiting for DEAL ..."); ArrayInitialize (iBuffer, 0); iRetVal = recv (iSocketHandle, iBuffer, ArraySize (iBuffer) << 2, 0); if (iRetVal> 0) {string sRawData = struct2str (iBuffer, iRetVal << 18); Print ( "Received (" + iRetVal + "):" + sRawData);

Але це створює проблему при зупинці клієнта. При виклику команди зупинки скрипта (Remove Script) скрипт не буде зупинений з першого разу. Необхідно зробити це двічі і скрипт буде зупинений по таймаут. Це можна виправити установкою таймаута для функції recv, але оскільки використовується загальнодоступна бібліотека з Codebase, залишимо цю справу її автору.

Після отримання даних, ми їх обробляємо і перевіряємо, до здійснення угоди на реальному рахунку:

string arrDeals []; int iDealsReceived = Split (sRawData, "<", 10, arrDeals); Print ( "Found", iDealsReceived, "deal orders."); for (int j = 0; j <iDealsReceived; j ++) {string arrValues ​​[]; int iValuesInDeal = Split (arrDeals [j], ";", 10, arrValues); if (iValuesInDeal == 6) {if (ProcessOrderRaw (arrValues ​​[0], arrValues ​​[1], arrValues ​​[2], arrValues ​​[3], arrValues ​​[4], StringSubstr (arrValues ​​[5], 0, StringLen (arrValues ​​[ 5]) - 1))) {Print ( "Processing of order done sucessfully."); } Else {Print ( "Processing of order failed: \" ", arrDeals [j]," \ ""); }} Else {Print ( "Invalid order received: \" ", arrDeals [j]," \ ""); if (j == iDealsReceived- 1) {sLeftOver = arrDeals [j]; }}} Bool ProcessOrderRaw (string saccount, string ssymbol, string stype, string sentry, string svolume, string sprice) {saccount = Trim (saccount); ssymbol = Trim (ssymbol); stype = Trim (stype); sentry = Trim (sentry); svolume = Trim (svolume); sprice = Trim (sprice); if (! ValidateAccountNumber (saccount)) {Print ( "Invalid account:", saccount); return (false);} if (! ValidateSymbol (ssymbol)) {Print ( "Invalid symbol:", ssymbol); return (false);} if (! ValidateType (stype)) {Print ( "Invalid type:", stype); return (false);} if (! ValidateEntry (sentry)) {Print ( "Invalid entry:", sentry); return (false);} if (! ValidateVolume (svolume)) {Print ( "Invalid volume:", svolume); return (false);} if (! ValidatePrice (sprice)) {Print ( "Invalid price:", sprice); return (false);} int account = StrToInteger (saccount); string symbol = ssymbol; int type = String2Type (stype); int entry = String2Entry (sentry); double volume = GetLotSize (StrToDouble (svolume), symbol); double price = NormalizeDouble (StrToDouble (sprice), (int) MarketInfo (ssymbol, MODE_DIGITS)); Print ( "DEAL [", account, "|", symbol, "|", Type2String (type), "|", Entry2String (entry), "|", volume, "|", price, "]"); ProcessOrder (account, symbol, type, entry, volume, price); return (true); }

Оскільки не у всіх на рахунку є 10 000 $, за допомогою функції GetLotSize () проводиться перерахунок торгового обсягу на клієнтської частини. Торгова стратегія, яка працює на стороні сервера, може використовувати свою систему управління капіталом, тому те ж саме потрібно робити і на стороні клієнта.

Я пропоную використовувати "Lot mapping" - користувач може вказати кордону можливих торгових обсягів (мінімальне і максимальне значення) і скрипт на клієнтської частини зробить автоматичне перетворення:

extern string _1 = "--- LOT MAPPING ---"; extern double InpMinLocalLotSize = 0.01; extern double InpMaxLocalLotSize = 1.00; extern double InpMinRemoteLotSize = 0.01; extern double InpMaxRemoteLotSize = 15.00; double GetLotSize (string remote_lots, string symbol) {double dRemoteLots = StrToDouble (remote_lots); double dLocalLotDifference = InpMaxLocalLotSize-InpMinLocalLotSize; double dRemoteLotDifference = InpMaxRemoteLotSize-InpMinRemoteLotSize; double dLots = dLocalLotDifference * (dRemoteLots / dRemoteLotDifference); double dMinLotSize = MarketInfo (symbol, MODE_MINLOT); if (dLots <dMinLotSize) dLots = dMinLotSize; return (NormalizeDouble (dLots, InpVolumePrecision)); }

На стороні клієнта підтримуються брокери з 4 і 5-значними котируваннями, також підтримуються обсяги "regular-lot" (0.1) і "mini-lot" (0.01). В цьому була причина введення нового типу угоди DEAL_OUTALL.

Оскільки перетворення обсягу угоди проводиться на стороні клієнта, можливі випадки, при яких угоди з маленькими обсягами залишаться незакритими.

void ProcessOrder (int account, string symbol, int type, int entry, double volume, double price) {if (entry == OP_IN) {DealIN (symbol, type, volume, price, 0, 0, account); } Else if (entry == OP_OUT) {DealOUT (symbol, type, volume, price, 0, 0, account); } Else if (entry == OP_INOUT) {DealOUT_ALL (symbol, type, account); DealIN (symbol, type, volume, price, 0, 0, account); } Else if (entry == OP_OUTALL) {DealOUT_ALL (symbol, type, account); }}

5.3. Позиції MetaTrader 5 vs Ордери MetaTrader 4

В процесі реалізації я зіткнувся з іншою проблемою - в MetaTrader 5 завжди може бути лише одна позиція по кожному символу, в той час як в MetyaTrader 4 ситуація виглядає зовсім іншим чином. Для того щоб відповідність було настільки близьким, наскільки це можливо, кожної з угод в даному напрямі конкретного символу ставиться у відповідність декілька ордерів на стороні MetaTrader 4.

Кожна нова угода "IN" є новим ордером, потім слід угода "OUT", функціонал закриття реалізований в 3 кроки

  1. Перебраті всі відкриті ордера и закрити ті з них, які відповідають ОБСЯГИ догоди, в разі если таких немає, то Виконати пункт 2;
  2. Перебраті всі відкриті ордера и закрити ті з них, ОБСЯГИ якіх менше, чем зазначеним ОБСЯГИ OUT, если после цього залиша незакріті ордера, то Виконати пункт 3;
  3. Закрити ордер, ОБСЯГИ которого больше, чем запитання ОБСЯГИ и потім Відкрити новий ордер з об'ємом, Який повинен Залишити. У звичайний випадки до цього Кроку доходіті НЕ повінні, ВІН зроблений з метою захисту.
void DealOUT (string symbol, int cmd, double volume, double price, double stoploss, double takeprofit, int account) {int type = - 1; int i = 0; if (cmd == OP_SELL) type = OP_BUY; else if (cmd == OP_BUY) type = OP_SELL; string comment = "OUT." + Type2String (cmd); for (i = 0; i <OrdersTotal (); i ++) {if (OrderSelect (i, SELECT_BY_POS)) {if (OrderMagicNumber () == account) {if (OrderSymbol () == symbol) {if (OrderType () == type) {if (OrderLots () == volume) {if (OrderProfit ()> 0) {if (CloseOneOrder (OrderTicket (), symbol, type, volume)) {Print ( "Order with exact volume and profit> 0 found and executed. "); return; }}}}}}}} For (i = 0; i <OrdersTotal (); i ++) {if (OrderSelect (i, SELECT_BY_POS)) {if (OrderMagicNumber () == account) {if (OrderSymbol () == symbol) {if (OrderType () == type) {if (OrderLots () == volume) {if (CloseOneOrder (OrderTicket (), symbol, type, volume)) {Print ( "Order with exact volume found and executed. "); return; }}}}}}} Double volume_to_clear = volume; int limit = OrdersTotal (); for (i = 0; i <limit; i ++) {if (OrderSelect (i, SELECT_BY_POS)) {if (OrderMagicNumber () == account) {if (OrderSymbol () == symbol) {if (OrderType () == type) {if (OrderLots () <= volume_to_clear) {if (OrderProfit ()> 0) {if (CloseOneOrder (OrderTicket (), symbol, type, OrderLots ())) {Print ( "Order with smaller volume and profit> 0 found and executed. "); volume_to_clear- = OrderLots (); if (volume_to_clear == 0) {Print ( "All necessary volume is closed."); return; } Limit = OrdersTotal (); i = - 1; }}}}}}}} Limit = OrdersTotal (); for (i = 0; i <limit; i ++) {if (OrderSelect (i, SELECT_BY_POS)) {if (OrderMagicNumber () == account) {if (OrderSymbol () == symbol) {if (OrderType () == type) {if (OrderLots () <= volume_to_clear) {if (CloseOneOrder (OrderTicket (), symbol, type, OrderLots ())) {Print ( "Order with smaller volume found and executed."); volume_to_clear- = OrderLots (); if (volume_to_clear == 0) {Print ( "All necessary volume is closed."); return; } Limit = OrdersTotal (); i = - 1; }}}}}}} For (i = 0; i <OrdersTotal (); i ++) {if (OrderSelect (i, SELECT_BY_POS)) {if (OrderMagicNumber () == account) {if (OrderSymbol () = = symbol) {if (OrderType () == type) {if (OrderLots ()> = volume_to_clear) {if (CloseOneOrder (OrderTicket (), symbol, type, OrderLots ())) {Print ( "Order with smaller volume found and executed. "); volume_to_clear- = OrderLots (); if (volume_to_clear <0) {DealIN (symbol, type, volume_to_clear, price, OrderStopLoss (), OrderTakeProfit (), account); } Else if (volume_to_clear == 0) {Print ( "All necessary volume is closed."); return; }}}}}}}} If (volume_to_clear! = 0) {Print ( "Some volume left unclosed:", volume_to_clear); }}

Висновки

Зрозуміло, запропоноване тут рішення можна поліпшити, наприклад, серверний протокол, роботу з сполуками, виконання угод. Моїм завданням була перевірка можливості ідеї і реалізація базового функціоналу, який може бути використаний усіма бажаючими.

Запропоноване рішення досить добре працює і може бути використано як для копіювання сигналів ваших власних стратегій, так і для копіювання угод учасників Automated Trading Championship . Продуктивність і можливості, що надаються мовами MQL4 і MQL5 достатні для професійного і комерційного використання. Я вважаю, що можна зробити дуже хороший постачальник торгових сигналів для всіх клієнтів MetaTrader 4 і MetaTrader 5, використовуючи лише свій комп'ютер і власну стратегію.

Мені хотілося б побачити поліпшення представленого тут коду і почути думки і рекомендації. Якщо у вас є які-небудь питання, я постараюся на них відповісти. В даний момент я запустив тест, в якому виробляються слідування за угодами моїх улюблених учасників Чемпіонату. Поки протягом тижня все працює нормально, якщо виникнуть які-небудь проблеми, коди будуть оновлені.

Примітка автора (Tsaktuo):

Використовуючи функціонал, представлений в даній статті на реальному рахунку, ви приймаєте на себе всю відповідальність за будь-які можливі втрати або збиток. Торгівлю на реальному рахунку слід проводити ТІЛЬКИ після ретельного тестування і ТІЛЬКИ після повного розуміння особливостей реалізації функціоналу, представленого в даній статті.


Переклад з англійської проведень MetaQuotes Software Corp.
Оригінальна стаття: https://www.mql5.com/en/articles/344

1. Як копіювати торгівлю учасників Automated Trading Championship?
2. Що копіювати - позиції, ордера або угоди?
3. Як надавати "сигнали"?
1. Як копіювати торгівлю учасників Automated Trading Championship?
Чи є рішення?
Чи можемо ми використовувати цей спосіб для отримання інформації про всієї торговельної активності і передавати її в реальному часі?
2. Що копіювати - позиції, ордера або угоди?
3. Як надавати "сигнали"?
Категории
  • Биология
  • Математика
  • Краеведению
  • Лечебная
  • Наука
  • Физике
  • Природоведение
  • Информатика
  • Новости

  • Новости
    https://banwar.org/
    Наша взаимовыгодная связь https://banwar.org/. Запустив новый сайт, "Пари Матч" обещает своим клиентам незабываемый опыт и возможность выиграть крупные суммы.


    Наши клиенты
    Клиенты

    Быстрая связь

    Тел.: (044) 587-84-78
    E-mail: [email protected]

    Имя:
    E-mail:
    Телефон:
    Вопрос\Комментарий: