18 января, 2010

Установка общего профита

Игорь Герасько
RU

Многим трейдерам отлично известна тактика Мартингейла – увеличение объема сделки после каждого полученного убытка. Эта тактика является гарантированно выигрышной, но как всегда имеет одно «но». Для полной гарантии получения прибыли нужно располагать бесконечно большими средствами. В этом и заключается основное противоречие. Зачем пытаться увеличивать капитал, если его размер и  без того бесконечен?

Тем не менее, в локальных масштабах применение тактики Мартингейла имеет право на жизнь. Например, такая модификация тактики как добавление к убыточной позиции. В данном случае упор делается на улучшение (уменьшение для длинных сделок и увеличение для коротких сделок) средней цены открытия совокупной сделки. Как следствие, для получения планируемой общей прибыли цене уже не нужно возвращаться к уровню профита первой позиции. Соответствующий новый уровень профита может быть расположен гораздо ближе к текущей цене, чем повышается вероятность его достижения.
Основной головной болью трейдера в применении такой тактики торговли является определение средней цены открытия нескольких однонаправленных сделок, равно как и общий уровень профита, который должен соответствовать значению той прибыли, которую планировалось получить еще при открытии самой первой позиции.
Помощником трейдера в этом случае может выступить обычный скрипт, который будет рассчитывать совокупный уровень профита так, будто прибыль была достигнута всего лишь одной сделкой.

Алгоритм работы скрипта следует из главной его функции — start:

int start()
{
// — 1 — =========== Получение информации о торговых условиях ===========
Tick = MarketInfo(Symbol(), MODE_TICKSIZE);                         // минимальный тик
TickValue = MarketInfo(Symbol(), MODE_TICKVALUE);   // стоимость тика в алюте депозита
Spread = ND(MarketInfo(Symbol(), MODE_SPREAD)*Point);                 // текущий спрэд
StopLevel = ND(MarketInfo(Symbol(), MODE_STOPLEVEL)*Point);  // текущий уровень стопов
// — 1 — ================ Окончание блока ========================

// — 2 — ================= Проверка правильности TakeProfit ============
if (TakeProfit <= (StopLevel-Spread)/Point)
{
Alert(«TakeProfit должен быть больше «, (StopLevel-Spread)/Point, » пунктов.»);
return(0);
}
if (Lots < MarketInfo(Symbol(), MODE_MINLOT))
{
Alert(«Указанное значение объема слишком мало!»);
return(0);
}
// — 2 — ==================== Окончание блока ====================

// — 3 — ================ Постоянный мониторинг позиций ==============
while (!IsStopped())
{
GetAveragePrices();                // Расчет средней цены открытия и общего профита
if (BuyProfit > 0 || SellProfit > 0)   // Если есть позиции по текущему инструменту
{
TickValue = MarketInfo(Symbol(), MODE_TICKVALUE); // цена тика в валюте депозита
Spread = ND(MarketInfo(Symbol(), MODE_SPREAD)*Point);           // текущий спрэд
StopLevel = ND(MarketInfo(Symbol(), MODE_STOPLEVEL)*Point);    // уровень стопов
SetCommonProfit();                // установка уровней профита на нужный уровень
}
}
// — 3 — ============= Окончание блока ===========================
return(0);
}

Первый блок просто собирает необходимую информацию – значение спрэда и минимального уровня стопов. Еще одним значением, которое потребуется при работе скрипта, является стоимость одного минимального изменения цены в валюте депозита. Иначе говоря, это стоимость одного тика на один полный лот.
Второй блок занимается проверкой правильности ввода пользователем двух входных параметров скрипта – TakeProfit и Lots.  Первый параметр задает количество пунктов планируемой прибыли, а второй – объем сделки, которым планируется получить эту прибыль.
Третий блок содержит «бесконечный цикл», который все же может быть закончен пользователем при отсоединении скрипта от графика. В теле цикла  рассчитывается совокупный уровень профита для длинных сделок (BuyProfit) и для коротких (SellProfit). Это делает функция GetAveragePrices. Следующим шагом является установка рассчитанного уровня профита для всех найденных позиций, чем занимается функция SetCommonProfit.

Функция GetAveragePrices работает таким образом:

void GetAveragePrices()
{
// — 1 — ======= Нахождение всех сделок по текущему инструменту ===========
BuyProfit = 0; SellProfit = 0;
double BuyAveragePrice = 0, SellAveragePrice = 0;
double BuyLots = 0, SellLots = 0;
for (int i = 0; i < OrdersTotal(); i++)
if (OrderSelect(i, SELECT_BY_POS))
if (OrderType() < 2)                                   // Учитываются только позиции
if (OrderSymbol() == Symbol())            // и только текущего инструмента
if (OrderType() == OP_BUY)
{
BuyAveragePrice += OrderOpenPrice()*OrderLots(); // Средняя цена открытия
BuyLots += OrderLots();       // и общий объем для длинных позиций
}
else
{
SellAveragePrice += OrderOpenPrice()*OrderLots();    // Средняя цена открытия
SellLots += OrderLots();          // и общий объем для коротких позиций
}
// — 1 — ============= Окончание блока ===========================

// — 2 — ====== Расчет общей цены закрытия сделок с учетом целевого профита ====
// сколько прибыли требуется в валюте депозита
double TargetProfit = TickValue*Lots*TakeProfit;
if (BuyLots != 0)
BuyProfit = BuyAveragePrice/BuyLots + Tick*(TargetProfit/(TickValue*BuyLots));
if (SellLots != 0)
SellProfit = SellAveragePrice/SellLots — Tick*(TargetProfit/(TickValue*SellLots));
// — 2 — ================ Окончание блока ========================
}

Далее рассчитывается уровень профита для длинных сделок BuyProfit. Для этого к средней цене открытия (отношение BuyAveragePrice к BuyLots) прибавляется выражение Tick*(TargetProfit/(TickValue*BuyLots)), которое разберем по частям. Итак, TickValue*BuyLots – это изменение средств (Equity) в валюте депозита с каждым тиком. Поэтому, если на него разделить планируемую прибыль (TargetProfit), то получим количество пунктов, которое нужно прибавить к средней цене открытия.
Точно также рассчитывается уровень профита для коротких позиций SellProfit.

Последняя рассматриваемая функция SetCommonProfit:

void SetCommonProfit()
{
// — 1 — ========= Нахождение позиций по текущему инструменту ===============
for (int i = 0; i < OrdersTotal(); i++)
if (OrderSelect(i, SELECT_BY_POS))
if (OrderType() < 2)                                   // Учитываются только позиции
if (OrderSymbol() == Symbol())              // и только текущего инструмента
// — 1 — ==================== Окончание блока ========================
{
double TP = 0;                             // Если 0, то не требуется изменение
// — 2 — ============== Проверка длинных позиций =======================
if (OrderType() == OP_BUY && BuyProfit > 0) // Если уровень профита рассчитан,
if (MathAbs(OrderTakeProfit() — BuyProfit) >= Tick &&    //отличается от текущего
BuyProfit — Bid > StopLevel)      // и расстояние для изменения достаточное
TP = NP(BuyProfit);
// — 2 — =============== Окончание блока =============================

// — 3 — ============ Проверка коротких позиций =========================
if (OrderType() == OP_SELL && SellProfit > 0)// Если уровень профита рассчитан,
if (MathAbs(OrderTakeProfit() — SellProfit) >= Tick&&    //отличается от текущего
Ask — SellProfit > StopLevel)         // и расстояние для изменения достаточное
TP = NP(SellProfit);
// — 3 — ===================== Окончание блока =======================

// — 4 — ============== Изменение уровня TakeProfit позиции =================
if (TP > 0)               // изменение требуется, если новый уровень не равен нулю
if (WaitForTradeContext())
if (!OrderModify(OrderTicket(), 0, OrderStopLoss(), TP, 0))
return;
// — 4 — ===================== Окончание блока =======================
}
}

Первый блок просто находит сделки по текущему инструменту.
Второй блок проверяет соответствие уровня профита найденной длинной сделки рассчитанному общему уровню BuyProfit. Если текущий уровень профита не равен рассчитанному и при этом текущее значение Bid достаточно далеко от BuyProfit, то будет произведено изменение уровня Take Profit сделки.
Третий блок является копией второго, с той лишь разницей, что работает с короткими позициями.
Четвертый блок занимается непосредственно модификацией уровня профита, которая происходит, если значение переменной TP не равно нулю.

Скрипт может быть использован как с одной, так и сразу с несколькими валютными парами одновременно. Его задачей является слежение за уровнем профита всех открываемых позиций. Поэтому при открытии очередной сделки уровень профита можно попросту не указывать.

В настройках скрипта достаточно указать количество пунктов прибыли, которое планируется получить (TakeProfit) и объем первой сделки (Lots), исходя из которого будет рассчитываться совокупная прибыль. Стоит учитывать, что результирующая прибыль будет немного отличаться от планируемой, правда, в лучшую сторону. Это происходит из-за невозможности указания дробного количества пунктов при установке целей каждой сделки.

После запуска скрипта трейдер должен вручную открывать сделки, указывая лишь уровень стоп-приказа. С открытием каждой новой сделки уровень профита каждой позиции автоматически будет изменяться скриптом.

Полный исходный код скрипта можно найти здесь.

Подпишитесь на нас в VK

Fortrader contentUrl Suite 11, Second Floor, Sound & Vision House, Francis Rachel Str. Victoria Victoria, Mahe, Seychelles +7 10 248 2640568

Ещё из этой категории

Все статьи

Простая разработка скрипта Stop Trade для MetaTrader 4 на языке Mql4

Торговля на финансовых рынках становится всё более популярной, и Алготрейдинг играет в этом процессе значительную роль. В этой статье мы рассмотрим простую разработку скрипта для MetaTrader 4, который закроет все открытые позиции и удалит все отложенные ордера. Скрипт будет написан на популярном языке программирования MQL4, который зарекомендовал себя как простой и надёжный инструмент для разработки […]

4 нюанса тестирования советников в терминале MetaTrader 4, о которых знают не все трейдеры

В условиях современного трейдинга использование в торговле форекс советников уже давно не выглядит какой-то экзотикой. Практически каждый день появляются новые платные и бесплатные торговые роботы, которые впечатляют доходностью и вызывают желание быстренько заработать. Однако ставить эксперта на торговый счет без проверки – сомнительная затея, ведущая к «неожиданным» потерям в потенциале. Поэтому рекомендуем начать работу с […]

Классификация Форекс советников

Форекс Советник (робот, EA) – это обыкновенный алгоритм, запрограммированный на основе той торговой системы, которой вы планируете использовать, чтобы совершать сделки на валютном рынке. Можно сказать, что для того, чтобы использовать советник, необходимо знать торговую систему, ставшую для него основой, чтобы знать, на каком рынке его можно применять, когда это делать по времени и за […]

Как написать торгового робота, если вы – не программист? 8 шагов от идеи до реализации

Головной мозг трейдера функционирует не совсем обычным образом. Человек, далекий от финансовых рынков, действует рационально и предсказуемо. Когда же в дело вступает индивид, мыслящий исключительно свечными комбинациями, последствия предсказать гораздо сложнее. Как частное, сбитые жизненные приоритеты и повышенная импульсивность – известные пороки трейдеров. Сам процесс торговли становиться самоцелью, и биологический компьютер в недрах черепной коробки […]

Недавние обучающие статьи

Все статьи

Редакция рекомендует

Все статьи
Loading...