BlueMoon EA
Сообщите нам, если считаете, что материал размещён без разрешения.
Сообщить о материале
Обращение по товару «bluemoon_ea_v3_4_netting_volume_fix.mq5» отправится на рассмотрение. Укажите контакт для ответа и опишите причину.
О программе
BlueMoon EA — торговый советник для платформы MetaTrader 5, работающий на сеттинг-счётах (неттинг). Советник анализирует ценовые данные с помощью скользящей средней и полос отклонения, формирует торговые сигналы на вход и управляет существующими позициями. Поддерживает сетку позиций в одном направлении, управление прибылью корзины и защиту от просадки.
Советник отслеживает рыночные события и открытые позиции, управляет ордерами через встроенный торговый класс CTrade. Реализует фильтрацию по спреду, проверку маржи и защиту от повторных заявок в одну и ту же секунду. При достижении заданного уровня просадки торговля блокируется.
В интерфейсе предусмотрена информационная панель с отображением текущего состояния, статуса сигналов, состава корзин, риск-метра и последней закрытой сделки. Панель настраивается по позиции и размеру шрифта.
Настройки программы
| Настройка | Описание |
|---|---|
| InpEAName | Название советника — Текстовое имя советника, отображаемое в интерфейсе и на панели. |
| InpMagicNumber | Магический номер — Уникальный идентификатор ордеров и позиций советника. |
| InpSignalTimeframe | Таймфрейм сигнала — Таймфрейм, на котором строится индикатор и генерируются торговые сигналы. |
| InpMAPeriod | Период MA — Период скользящей средней, используемой для расчёта базовой линии. |
| InpMAMethod | Метод MA — Тип скользящей средней (например, EMA, SMA) для расчёта базовой линии. |
| InpEnvelopeDeviationPercent | Отклонение энvelope в процентах — Процентное отклонение полос от базовой линии скользящей средней. |
| InpInitialLot | Начальный лот — Размер лота для первого входящего ордера. |
| InpLotIncrement | Приращение лота — Увеличение размера лота на каждом следующем уровне сетки. |
| InpMaxLot | Максимальный лот — Максимально допустимый размер лота для одной позиции. |
| InpGridDistancePips | Расстояние сетки в пипсах — Расстояние в пипсах между уровнями сетки для наращивания позиции. |
| InpSingleTradeTPPips | Тейк-профит для одной сделки в пипсах — Фиксированный тейк-профит в пипсах для закрытия позиции, содержащей один уровень сетки. |
| InpBasketProfitTargetMoney | Цель прибыли корзины — Целевая сумма чистой прибыли корзины позиций в одном направлении для её закрытия. |
| InpMaxPositionsPerDirection | Максимум позиций в направлении — Максимальное количество уровней сетки в одном торговом направлении. |
| InpTradeOnlyOnNewBar | Торговать только на новом баре — Разрешает открытие новых позиций только при появлении нового бара на сигнальном таймфрейме. |
| InpUseClosedBarSignal | Использовать сигнал закрытого бара — Использовать данные закрытой свечи для формирования сигнала на вход вместо текущих цен. |
| InpAllowBuy | Разрешить покупку — Разрешает открытие длинных позиций при наличии сигнала на покупку. |
| InpAllowSell | Разрешить продажу — Разрешает открытие коротких позиций при наличии сигнала на продажу. |
| InpAllowRecentSignalOnStartup | Разрешить недавний сигнал при запуске — При запуске советника пытается восстановить сигнал с недавно закрытой свечи. |
| InpMaxSignalAgeBars | Максимальный возраст сигнала в барах — Максимальное количество баров назад, в пределах которых ищется подходящий сигнал при запуске. |
| InpRecentSignalMaxDistancePips | Максимальное расстояние недавнего сигнала в пипсах — Допустимое расстояние в пипсах между ценой и уровнем сигнала для его восстановления при запуске. |
| InpMaxSpreadPips | Максимальный спред в пипсах — Максимально допустимый спред в пипсах для открытия новых позиций. |
| InpSlippagePoints | Проскальзывание в пунктах — Допустимое проскальзывание в пунктах при исполнении ордеров. |
| InpEnableTotalDrawdownProtection | Включить защиту от просадки — Активирует блокировку торговли при достижении заданного уровня просадки. |
| InpMaxTotalDrawdownPercent | Максимальная просадка в процентах — Порог просадки, при достижении которого срабатывает защита и блокировка торговли. |
| InpUsePeakEquityForDrawdown | Использовать пиковое эквити для просадки — При включении расчёт просадки ведётся от пикового значения эквити, а не от баланса. |
| InpLockTradingAfterDD | Блокировка торговли после просадки — После срабатывания защиты от просадки торговля блокируется до перезапуска советника. |
| InpShowDashboard | Показывать панель — Включает отображение информационной панели на графике. |
| InpDashboardX | Позиция панели X — Горизонтальная координата левого верхнего угла панели в пикселях. |
| InpDashboardY | Позиция панели Y — Вертикальная координата левого верхнего угла панели в пикселях. |
| InpDashboardWidth | Ширина панели — Ширина информационной панели в пикселях. |
| InpDashboardFontSize | Размер шрифта панели — Размер шрифта текста на информационной панели. |
Поиск по коду файла
#property strict
#property version "3.40"
#property description "BlueMoon EA - "
#include <Trade/Trade.mqh>
CTrade trade;
input string InpEAName = "BlueMoon EA";
input ulong InpMagicNumber = 31072026;
input ENUM_TIMEFRAMES InpSignalTimeframe = PERIOD_M5;
input int InpMAPeriod = 14;
input ENUM_MA_METHOD InpMAMethod = MODE_EMA;
input double InpEnvelopeDeviationPercent = 0.10;
input double InpInitialLot = 0.01;
input double InpLotIncrement = 0.01;
input double InpMaxLot = 0.10;
input int InpGridDistancePips = 17;
input int InpSingleTradeTPPips = 10;
input double InpBasketProfitTargetMoney = 1.00;
input int InpMaxPositionsPerDirection = 10;
input bool InpTradeOnlyOnNewBar = true;
input bool InpUseClosedBarSignal = true;
input bool InpAllowBuy = true;
input bool InpAllowSell = true;
input bool InpAllowRecentSignalOnStartup = true;
input int InpMaxSignalAgeBars = 2;
input double InpRecentSignalMaxDistancePips = 3.0;
input double InpMaxSpreadPips = 2.50;
input int InpSlippagePoints = 20;
input bool InpEnableTotalDrawdownProtection = true;
input double InpMaxTotalDrawdownPercent = 51.0;
input bool InpUsePeakEquityForDrawdown = true;
input bool InpCloseAllAccountPositionsOnDD = false;
input bool InpLockTradingAfterDD = true;
input bool InpShowDashboard = true;
input int InpDashboardX = 12;
input int InpDashboardY = 22;
input int InpDashboardWidth = 420;
input int InpDashboardFontSize = 9;
int maHandle = INVALID_HANDLE;
datetime lastSignalBar = 0;
double peakEquity = 0.0;
bool drawdownLock = false;
string currentStatus = "INITIALISING";
string blockingReason = "";
string lastAction = "None";
string lastCloseReason = "No BlueMoon trade closed yet";
datetime lastTickTime = 0;
bool startupSignalChecked = false;
string PREFIX = "BM34_";
bool isNettingAccount = false;
datetime lastBuyAttemptTime = 0;
datetime lastSellAttemptTime = 0;
double lastBuyAttemptPrice = 0.0;
double lastSellAttemptPrice = 0.0;
double PipSize()
{
int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
return (digits == 3 || digits == 5) ? point * 10.0 : point;
}
double CurrentSpreadPips()
{
MqlTick tick;
if(!SymbolInfoTick(_Symbol, tick)) return 0.0;
return (tick.ask - tick.bid) / PipSize();
}
double NormalizeVolume(double volume)
{
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
double step = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
volume = MathMax(minLot, MathMin(maxLot, volume));
if(step > 0.0)
volume = MathFloor(volume / step + 1e-8) * step;
int volDigits = 2;
if(step == 0.1) volDigits = 1;
else if(step == 0.001) volDigits = 3;
return NormalizeDouble(volume, volDigits);
}
bool IsOurPositionByIndex(int index)
{
ulong ticket = PositionGetTicket(index);
if(ticket == 0) return false;
if(!PositionSelectByTicket(ticket)) return false;
return ((ulong)PositionGetInteger(POSITION_MAGIC) == InpMagicNumber &&
PositionGetString(POSITION_SYMBOL) == _Symbol);
}
int CountPositions(ENUM_POSITION_TYPE type)
{
int count = 0;
for(int i = PositionsTotal() - 1; i >= 0; --i)
{
if(!IsOurPositionByIndex(i)) continue;
if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == type)
count++;
}
return count;
}
double TotalLots(ENUM_POSITION_TYPE type)
{
double lots = 0.0;
for(int i = PositionsTotal() - 1; i >= 0; --i)
{
if(!IsOurPositionByIndex(i)) continue;
if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == type)
lots += PositionGetDouble(POSITION_VOLUME);
}
return lots;
}
int CountGridLevels(ENUM_POSITION_TYPE type)
{
if(!isNettingAccount)
return CountPositions(type);
double total = TotalLots(type);
if(total <= 0.0) return 0;
double accumulated = 0.0;
for(int level = 0; level < InpMaxPositionsPerDirection; ++level)
{
double levelLot = NormalizeVolume(MathMin(InpMaxLot,
InpInitialLot + level * InpLotIncrement));
accumulated += levelLot;
double step = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
double tolerance = MathMax(step * 0.51, 1e-8);
if(total <= accumulated + tolerance)
return level + 1;
}
return InpMaxPositionsPerDirection;
}
double CurrentSymbolDirectionalVolume(ENUM_ORDER_TYPE orderType)
{
double volume = 0.0;
ENUM_POSITION_TYPE wanted = (orderType == ORDER_TYPE_BUY ?
POSITION_TYPE_BUY : POSITION_TYPE_SELL);
for(int i = PositionsTotal() - 1; i >= 0; --i)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0 || !PositionSelectByTicket(ticket)) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == wanted)
volume += PositionGetDouble(POSITION_VOLUME);
}
for(int i = OrdersTotal() - 1; i >= 0; --i)
{
ulong ticket = OrderGetTicket(i);
if(ticket == 0 || !OrderSelect(ticket)) continue;
if(OrderGetString(ORDER_SYMBOL) != _Symbol) continue;
ENUM_ORDER_TYPE t = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
bool sameDirection = (orderType == ORDER_TYPE_BUY &&
(t == ORDER_TYPE_BUY_LIMIT || t == ORDER_TYPE_BUY_STOP ||
t == ORDER_TYPE_BUY_STOP_LIMIT)) ||
(orderType == ORDER_TYPE_SELL &&
(t == ORDER_TYPE_SELL_LIMIT || t == ORDER_TYPE_SELL_STOP ||
t == ORDER_TYPE_SELL_STOP_LIMIT));
if(sameDirection)
volume += OrderGetDouble(ORDER_VOLUME_CURRENT);
}
return volume;
}
double LastEntryDealPrice(ENUM_POSITION_TYPE type)
{
if(!HistorySelect(0, TimeCurrent())) return 0.0;
ENUM_DEAL_TYPE wanted = (type == POSITION_TYPE_BUY ? DEAL_TYPE_BUY : DEAL_TYPE_SELL);
for(int i = HistoryDealsTotal() - 1; i >= 0; --i)
{
ulong deal = HistoryDealGetTicket(i);
if(deal == 0) continue;
if((ulong)HistoryDealGetInteger(deal, DEAL_MAGIC) != InpMagicNumber) continue;
if(HistoryDealGetString(deal, DEAL_SYMBOL) != _Symbol) continue;
if((ENUM_DEAL_TYPE)HistoryDealGetInteger(deal, DEAL_TYPE) != wanted) continue;
ENUM_DEAL_ENTRY entry = (ENUM_DEAL_ENTRY)HistoryDealGetInteger(deal, DEAL_ENTRY);
if(entry == DEAL_ENTRY_IN || entry == DEAL_ENTRY_INOUT)
return HistoryDealGetDouble(deal, DEAL_PRICE);
}
return 0.0;
}
double BasketNet(ENUM_POSITION_TYPE type)
{
double net = 0.0;
for(int i = PositionsTotal() - 1; i >= 0; --i)
{
if(!IsOurPositionByIndex(i)) continue;
if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) != type) continue;
net += PositionGetDouble(POSITION_PROFIT);
net += PositionGetDouble(POSITION_SWAP);
}
return net;
}
double BasketSwap(ENUM_POSITION_TYPE type)
{
double value = 0.0;
for(int i = PositionsTotal() - 1; i >= 0; --i)
{
if(!IsOurPositionByIndex(i)) continue;
if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == type)
value += PositionGetDouble(POSITION_SWAP);
}
return value;
}
double WeightedAverageEntry(ENUM_POSITION_TYPE type)
{
double weighted = 0.0, lots = 0.0;
for(int i = PositionsTotal() - 1; i >= 0; --i)
{
if(!IsOurPositionByIndex(i)) continue;
if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) != type) continue;
double v = PositionGetDouble(POSITION_VOLUME);
weighted += PositionGetDouble(POSITION_PRICE_OPEN) * v;
lots += v;
}
return (lots > 0.0 ? weighted / lots : 0.0);
}
double NewestEntry(ENUM_POSITION_TYPE type)
{
datetime newestTime = 0;
double newestPrice = 0.0;
for(int i = PositionsTotal() - 1; i >= 0; --i)
{
if(!IsOurPositionByIndex(i)) continue;
if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) != type) continue;
datetime t = (datetime)PositionGetInteger(POSITION_TIME);
if(t >= newestTime)
{
newestTime = t;
newestPrice = PositionGetDouble(POSITION_PRICE_OPEN);
}
}
return newestPrice;
}
double OldestEntry(ENUM_POSITION_TYPE type)
{
datetime oldestTime = D'2099.12.31';
double oldestPrice = 0.0;
for(int i = PositionsTotal() - 1; i >= 0; --i)
{
if(!IsOurPositionByIndex(i)) continue;
if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) != type) continue;
datetime t = (datetime)PositionGetInteger(POSITION_TIME);
if(t <= oldestTime)
{
oldestTime = t;
oldestPrice = PositionGetDouble(POSITION_PRICE_OPEN);
}
}
return oldestPrice;
}
double NextLot(ENUM_POSITION_TYPE type)
{
int count = CountGridLevels(type);
return NormalizeVolume(MathMin(InpMaxLot, InpInitialLot + count * InpLotIncrement));
}
bool IsNewSignalBar()
{
datetime bar = iTime(_Symbol, InpSignalTimeframe, 0);
if(bar == 0) return false;
if(bar != lastSignalBar)
{
lastSignalBar = bar;
return true;
}
return false;
}
bool GetEnvelope(double ¢er, double &upper, double &lower)
{
double ma[1];
if(CopyBuffer(maHandle, 0, 0, 1, ma) != 1) return false;
center = ma[0];
double deviation = InpEnvelopeDeviationPercent / 100.0;
upper = center * (1.0 + deviation);
lower = center * (1.0 - deviation);
return true;
}
bool GetEnvelopeAtShift(int shift, double ¢er, double &upper, double &lower)
{
if(shift < 0) return false;
double ma[1];
if(CopyBuffer(maHandle, 0, shift, 1, ma) != 1) return false;
center = ma[0];
double deviation = InpEnvelopeDeviationPercent / 100.0;
upper = center * (1.0 + deviation);
lower = center * (1.0 - deviation);
return true;
}
double CurrentDrawdownPercent()
{
double equity = AccountInfoDouble(ACCOUNT_EQUITY);
double base = AccountInfoDouble(ACCOUNT_BALANCE);
if(InpUsePeakEquityForDrawdown)
{
if(equity > peakEquity) peakEquity = equity;
base = MathMax(base, peakEquity);
}
if(base <= 0.0) return 0.0;
return MathMax(0.0, (base - equity) / base * 100.0);
}
void DeletePendingOrders(bool allAccountOrders)
{
for(int i = OrdersTotal() - 1; i >= 0; --i)
{
ulong ticket = OrderGetTicket(i);
if(ticket == 0 || !OrderSelect(ticket)) continue;
if(!allAccountOrders)
{
if((ulong)OrderGetInteger(ORDER_MAGIC) != InpMagicNumber) continue;
if(OrderGetString(ORDER_SYMBOL) != _Symbol) continue;
}
trade.OrderDelete(ticket);
}
}
void ClosePositions(bool allAccountPositions, string reason)
{
lastCloseReason = reason;
lastAction = reason;
for(int i = PositionsTotal() - 1; i >= 0; --i)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0 || !PositionSelectByTicket(ticket)) continue;
if(!allAccountPositions)
{
if((ulong)PositionGetInteger(POSITION_MAGIC) != InpMagicNumber) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
}
trade.PositionClose(ticket, InpSlippagePoints);
}
DeletePendingOrders(allAccountPositions);
}
void ClosePositionsByType(ENUM_POSITION_TYPE type, string reason)
{
lastCloseReason = reason;
lastAction = reason;
for(int i = PositionsTotal() - 1; i >= 0; --i)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0 || !PositionSelectByTicket(ticket)) continue;
if((ulong)PositionGetInteger(POSITION_MAGIC) != InpMagicNumber) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) != type) continue;
if(!trade.PositionClose(ticket, InpSlippagePoints))
Print("BlueMoon close failed for ticket ", ticket, ": ",
trade.ResultRetcode(), " ", trade.ResultRetcodeDescription());
}
}
bool CheckDrawdownProtection()
{
double dd = CurrentDrawdownPercent();
if(!InpEnableTotalDrawdownProtection) return false;
if(dd < InpMaxTotalDrawdownPercent) return false;
currentStatus = "DRAWDOWN PROTECTION TRIGGERED";
blockingReason = StringFormat("Total drawdown %.2f%% reached %.2f%% limit",
dd, InpMaxTotalDrawdownPercent);
ClosePositions(InpCloseAllAccountPositionsOnDD,
StringFormat("TOTAL DRAWDOWN STOP %.2f%%", dd));
if(InpLockTradingAfterDD)
drawdownLock = true;
return true;
}
bool CanOpenPosition(ENUM_ORDER_TYPE orderType, double volume, string &reason)
{
reason = "";
if(!TerminalInfoInteger(TERMINAL_CONNECTED))
{
reason = "Terminal is not connected";
return false;
}
if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) ||
!MQLInfoInteger(MQL_TRADE_ALLOWED) ||
!AccountInfoInteger(ACCOUNT_TRADE_ALLOWED))
{
reason = "Automated trading is not allowed";
return false;
}
long tradeMode = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_MODE);
if(tradeMode == SYMBOL_TRADE_MODE_DISABLED || tradeMode == SYMBOL_TRADE_MODE_CLOSEONLY)
{
reason = "Symbol is not open for new trades";
return false;
}
if(orderType == ORDER_TYPE_BUY && tradeMode == SYMBOL_TRADE_MODE_SHORTONLY)
{
reason = "Symbol allows sell orders only";
return false;
}
if(orderType == ORDER_TYPE_SELL && tradeMode == SYMBOL_TRADE_MODE_LONGONLY)
{
reason = "Symbol allows buy orders only";
return false;
}
MqlTick tick;
if(!SymbolInfoTick(_Symbol, tick) || tick.ask <= 0.0 || tick.bid <= 0.0)
{
reason = "Valid market prices are unavailable";
return false;
}
volume = NormalizeVolume(volume);
double symbolVolumeLimit = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_LIMIT);
if(symbolVolumeLimit > 0.0)
{
double used = CurrentSymbolDirectionalVolume(orderType);
double step = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
double tolerance = MathMax(step * 0.1, 1e-8);
if(used + volume > symbolVolumeLimit + tolerance)
{
reason = StringFormat("Broker volume limit reached: used %.2f + requested %.2f > %.2f",
used, volume, symbolVolumeLimit);
return false;
}
}
double price = (orderType == ORDER_TYPE_BUY ? tick.ask : tick.bid);
double margin = 0.0;
if(!OrderCalcMargin(orderType, _Symbol, volume, price, margin))
{
reason = StringFormat("Margin calculation failed: %d", GetLastError());
return false;
}
if(AccountInfoDouble(ACCOUNT_MARGIN_FREE) < margin)
{
reason = StringFormat("Insufficient free margin: need %.2f", margin);
return false;
}
return true;
}
bool OpenPosition(ENUM_ORDER_TYPE orderType, double volume, string comment)
{
volume = NormalizeVolume(volume);
MqlTick attemptTick;
if(!SymbolInfoTick(_Symbol, attemptTick)) return false;
datetime now = TimeCurrent();
double attemptPrice = (orderType == ORDER_TYPE_BUY ? attemptTick.ask : attemptTick.bid);
datetime previousTime = (orderType == ORDER_TYPE_BUY ? lastBuyAttemptTime : lastSellAttemptTime);
double previousPrice = (orderType == ORDER_TYPE_BUY ? lastBuyAttemptPrice : lastSellAttemptPrice);
double minMove = MathMax(SymbolInfoDouble(_Symbol, SYMBOL_POINT), PipSize() * 0.1);
if(previousTime == now && MathAbs(attemptPrice - previousPrice) < minMove)
{
currentStatus = "DUPLICATE ORDER SUPPRESSED";
blockingReason = "An identical order attempt was already made on this tick/second";
return false;
}
if(orderType == ORDER_TYPE_BUY)
{
lastBuyAttemptTime = now;
lastBuyAttemptPrice = attemptPrice;
}
else
{
lastSellAttemptTime = now;
lastSellAttemptPrice = attemptPrice;
}
string validationReason;
if(!CanOpenPosition(orderType, volume, validationReason))
{
currentStatus = "ORDER BLOCKED";
blockingReason = validationReason;
lastAction = validationReason;
return false;
}
trade.SetExpertMagicNumber(InpMagicNumber);
trade.SetDeviationInPoints(InpSlippagePoints);
bool ok = false;
if(orderType == ORDER_TYPE_BUY)
ok = trade.Buy(volume, _Symbol, 0.0, 0.0, 0.0, comment);
else if(orderType == ORDER_TYPE_SELL)
ok = trade.Sell(volume, _Symbol, 0.0, 0.0, 0.0, comment);
if(ok)
{
lastAction = StringFormat("Opened %s %.2f lot",
orderType == ORDER_TYPE_BUY ? "BUY" : "SELL", volume);
}
else
{
lastAction = StringFormat("Order failed: %d %s",
trade.ResultRetcode(), trade.ResultRetcodeDescription());
}
return ok;
}
void ManageSingleTradeTP(ENUM_POSITION_TYPE type)
{
if(CountGridLevels(type) != 1) return;
MqlTick tick;
if(!SymbolInfoTick(_Symbol, tick)) return;
double entry = WeightedAverageEntry(type);
double pips = 0.0;
if(type == POSITION_TYPE_BUY)
pips = (tick.bid - entry) / PipSize();
else
pips = (entry - tick.ask) / PipSize();
if(pips >= InpSingleTradeTPPips)
{
ClosePositionsByType(type, "SINGLE TRADE TAKE PROFIT");
currentStatus = "SINGLE TRADE TP CLOSED";
}
}
void ManageBasketProfit(ENUM_POSITION_TYPE type)
{
int count = CountGridLevels(type);
if(count < 2) return;
double net = BasketNet(type);
if(net >= InpBasketProfitTargetMoney)
{
ClosePositionsByType(type, "BASKET PROFIT TARGET");
currentStatus = "BASKET TARGET CLOSED";
}
}
void ManageGrid(ENUM_POSITION_TYPE type)
{
int count = CountGridLevels(type);
if(count <= 0 || count >= InpMaxPositionsPerDirection) return;
MqlTick tick;
if(!SymbolInfoTick(_Symbol, tick)) return;
double newest = (isNettingAccount ? LastEntryDealPrice(type) : NewestEntry(type));
if(newest <= 0.0) newest = WeightedAverageEntry(type);
if(newest <= 0.0) return;
double distancePips = 0.0;
if(type == POSITION_TYPE_BUY)
distancePips = (newest - tick.ask) / PipSize();
else
distancePips = (tick.bid - newest) / PipSize();
if(distancePips >= InpGridDistancePips)
{
double lot = NextLot(type);
bПоказано первые 50% кода (символов: 28199)
Открыть по тарифу
Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.
Разовая покупка файла
На этой странице откроется полный исходный код файла вместо ознакомительного фрагмента.
Зачем нужен email? После подтверждения оплаты файл сохранится в кабинете на этот email. Если аккаунта ещё нет, мы создадим его и пришлём ссылку для задания пароля. Если аккаунт уже есть, покупка добавится в него. Укажите адрес, к которому у вас есть доступ.
Чтобы оформить заказ, введите email и перейдите к оплате.