После создания заготовки скрипта нужно прописать свойство:
- Код: выделить все
#property script_show_inputs
Чтобы скрипт мог при запуске получать от пользователя вводимые значения переменных (настройки).
Теперь нам надо организовать выбор пользователем тринов, т.е. заранее организовать список треугольников. Это необходимо потому, что, во-первых, пользователь может не помнить какие именно валютные пары входят в тот или иной трин, во-вторых, последовательность валютных пар в треугольнике жестко фиксирована, т.е. пары менять местами нельзя.
Нам не нужно вводить сразу же все возможные трины. Обычно торгуется один-два трина из мажорных пар. Но со временем, можно пополнять будет список тринов, скажем, в новых версиях. Сейчас главное создать прототип, вообще, для помощи рассчета лотов трейдерам, которые ни бум-бум в этой теме.
Организуем трины через перечисления:
- Код: выделить все
enum enuTri
{
EURUSD_GBPUSD_EURGBP = 1,
EURCHF_USDCHF_EURUSD = 2,
};
Заодно сразу же организуем выбор направления торговли для тринов и также через перечисления.
Направления торговли трина могут быть двух типов:
BUY-SELL-SELL и
SELL-BUY-BUY.
Это и организуем:
- Код: выделить все
enum enuDir
{
BUY_SELL_SELL = 1,
SELL_BUY_BUY = 2,
};
Введем две перепенные для работы с упомянутыми перечислениями. На данном этапе код наш будет выглядеть так:
- Код: выделить все
//+------------------------------------------------------------------+
//| SC-TrinLot-v1.mq4 |
//| Haos |
//| |
//+------------------------------------------------------------------+
#property copyright "Haos"
#property link "https://investforum.ru/forum"
#property version "1.00"
#property strict
#property script_show_inputs
//***********************************************************************************************
enum enuTri
{
EURUSD_GBPUSD_EURGBP = 1,
EURCHF_USDCHF_EURUSD = 2,
};
enum enuDir
{
BUY_SELL_SELL = 1,
SELL_BUY_BUY = 2,
};
//***********************************************************************************************
input enuTri intTri = 1; // Трин для торговли
input enuDir intDir = 1; // Направление торговли трина
//***********************************************************************************************
void OnStart()
{
}
Из переменных, вводимых пользователем, надо предусмотреть размер лота первой пары трина. Для второй и третьей пары расчет будет производить скрипт:
- Код: выделить все
input double dblQ1 = 0.1; // Размер торгового лота 1-ой пары трина
Теперь к самой процедуре OnStart() перейдем.
Прежде всего сформируем переменные:
- Код: выделить все
double dblQ2, dblQ3;
string strP1, strP2, strP3;
int intLoDi = 2;
dblQ2, dblQ3 - размер лотов для 2-ой и 3-ей пары;
strP1, strP2, strP3 - имена торговых пар трина;
intLoDi - кол-во знаков после точки в размере лота. По умолчанию инициализируем значением 2, но в процедуре произведем перерасчет (хотя, еще не встретились нам ни разу, чтобы размер лота после точки не был равен двум).
Организуем перебор тринов, в переключателе switch. Будем в нем инициализировать нужные переменные, а также производить вычисление размеров лота трина по правилам, указанным в статье Справочник по треугольному арбитражу.
В результате код для OnStart() будет иметь вид:
- Код: выделить все
void OnStart()
{
double dblQ2, dblQ3;
string strP1, strP2, strP3;
int intLoDi = 2;
switch(intTri)
{
case 1:
// EURUSD_GBPUSD_EURGBP
strP1 = "EURUSD"; strP2 = "GBPUSD"; strP3 = "EURGBP";
intLoDi = f_GetLotDigits(strP1);
dblQ3 = dblQ1;
if(intDir == 1) // BUY_SELL_SELL
{
dblQ2 = NormalizeDouble(dblQ1 * MarketInfo(strP3, MODE_BID), intLoDi);
}
else if(intDir == 2) // SELL_BUY_BUY
{
dblQ2 = NormalizeDouble(dblQ1 * MarketInfo(strP3, MODE_ASK), intLoDi);
}
break;
case 2:
//EURCHF_USDCHF_EURUSD
strP1 = "EURCHF"; strP2 = "USDCHF"; strP3 = "EURUSD";
intLoDi = f_GetLotDigits(strP1);
dblQ3 = dblQ1;
if(intDir == 1) // BUY_SELL_SELL
{
dblQ2 = NormalizeDouble(dblQ1 * MarketInfo(strP3, MODE_BID), intLoDi);
}
else if(intDir == 2) // SELL_BUY_BUY
{
dblQ2 = NormalizeDouble(dblQ1 * MarketInfo(strP3, MODE_ASK), intLoDi);
}
break;
break;
}
Comment( "\n", "Размер лотов треугольника: ",
"\n", strP1," = ", DoubleToStr(dblQ1, intLoDi),
"\n", strP2," = ", DoubleToStr(dblQ2, intLoDi),
"\n", strP3," = ", DoubleToStr(dblQ3, intLoDi));
}
При этом, вывод полученных значений организуем в виде комментария, выводимого в левый верхний угол окна с графиком валютной пары. Запускать скрипт можно в любом окне, от окна расчет не зависит.
Итак, окончательно код скрипта будет выглядеть так:
- Код: выделить все
//+------------------------------------------------------------------+
//| SC-TrinLot-v1.mq4 |
//| Haos |
//| |
//+------------------------------------------------------------------+
#property copyright "Haos"
#property link "https://investforum.ru/forum"
#property version "1.00"
#property strict
#property script_show_inputs
//***********************************************************************************************
enum enuTri
{
EURUSD_GBPUSD_EURGBP = 1,
EURCHF_USDCHF_EURUSD = 2,
};
enum enuDir
{
BUY_SELL_SELL = 1,
SELL_BUY_BUY = 2,
};
//***********************************************************************************************
input enuTri intTri = 1; // Трин для торговли
input enuDir intDir = 1; // Направление торговли трина
input double dblQ1 = 0.1; // Размер торгового лота 1-ой пары трина
//***********************************************************************************************
void OnStart()
{
double dblQ2, dblQ3;
string strP1, strP2, strP3;
int intLoDi = 2;
switch(intTri)
{
case 1:
// EURUSD_GBPUSD_EURGBP
strP1 = "EURUSD"; strP2 = "GBPUSD"; strP3 = "EURGBP";
intLoDi = f_GetLotDigits(strP1);
dblQ3 = dblQ1;
if(intDir == 1) // BUY_SELL_SELL
{
dblQ2 = NormalizeDouble(dblQ1 * MarketInfo(strP3, MODE_BID), intLoDi);
}
else if(intDir == 2) // SELL_BUY_BUY
{
dblQ2 = NormalizeDouble(dblQ1 * MarketInfo(strP3, MODE_ASK), intLoDi);
}
break;
case 2:
//EURCHF_USDCHF_EURUSD
strP1 = "EURCHF"; strP2 = "USDCHF"; strP3 = "EURUSD";
intLoDi = f_GetLotDigits(strP1);
dblQ3 = dblQ1;
if(intDir == 1) // BUY_SELL_SELL
{
dblQ2 = NormalizeDouble(dblQ1 * MarketInfo(strP3, MODE_BID), intLoDi);
}
else if(intDir == 2) // SELL_BUY_BUY
{
dblQ2 = NormalizeDouble(dblQ1 * MarketInfo(strP3, MODE_ASK), intLoDi);
}
break;
break;
}
Comment( "\n", "Размер лотов треугольника: ",
"\n", strP1," = ", DoubleToStr(dblQ1, intLoDi),
"\n", strP2," = ", DoubleToStr(dblQ2, intLoDi),
"\n", strP3," = ", DoubleToStr(dblQ3, intLoDi));
}
//***********************************************************************************************
int f_GetLotDigits(string sy)
{
/*
Описание : Количество цифр после запятой в величине лота
Параметры:
sy - наименование инструмента ("0" - текущий символ)
*/
if(sy == "0") sy = _Symbol;
return((int)MathLog10(1 / MarketInfo(sy, MODE_LOTSTEP)));
}
Очевидно, что скрипт есть куда улучшать. Написан он, прямо скажем, "в лоб". Можно ввести массив для наименований пар, нужно учесть ситуацию, когда наименования отличаются от классических и имеют постфиксы в виде буквы. Можно сократить код, введением функций в которых однотипные операции вынести и т.д.
Предлагаю это всё осуществить заинтересованному читателю. Заготовочка имеется, задача решена по расчету размеров лота для треугольника. Дальше, как говорится "доработать напильником" остается.

Скрин запуска скрипта по параметрам, установленным по умолчанию: