automated ea hedging type strategy.mq4
Сообщите нам, если считаете, что материал размещён без разрешения.
Сообщить о материале
Обращение по товару «automated ea hedging type strategy.mq4» отправится на рассмотрение. Укажите контакт для ответа и опишите причину.
О программе
Программа представляет собой торговый советник для MetaTrader 4, реализующий стратегию хеджирования. При отключённом ручном режиме (ManualMode) советник в обработчике OnTick открывает рыночную покупку с начальным размером лота. Класс TradingMonitor отслеживает открытые ордера: при обнаружении нового ордера он создаёт противоположный ордер (продажу) на заданном расстоянии в пипах от цены открытия первого ордера, формируя хедж.
Советник поддерживает до шести различных размеров лотов для длинных и коротких позиций, а также отдельные уровни тейк-профита для каждой стороны (в пипах). Параметры проскальзывания и магического номера управляют исполнением и фильтрацией ордеров. При закрытии сделки TradingMonitor удаляет ордера с заданным магическим номером и закрывает оставшиеся позиции.
В ручном режиме автоматическое открытие ордеров отключено, что позволяет пользователю управлять позициями самостоятельно. Класс OrderBuilder формирует ордера с учётом стоп-лосса, тейк-профита и магического номера, а класс TradeCalculator рассчитывает параметры сделок на основе рыночных данных.
Настройки программы
| Настройка | Описание |
|---|---|
| Manual mode? (ManualMode) | ManualMode — Manual mode? |
| Initial amount (InitialAmount) | InitialAmount — Initial amount |
| == General == (GeneralSection) | GeneralSection — == General == |
| Long take profit (LongTakeProfit) | LongTakeProfit — Long take profit |
| Long lot size #1 (LongLotSize1) | LongLotSize1 — Long lot size #1 |
| Long lot size #2 (LongLotSize2) | LongLotSize2 — Long lot size #2 |
| Long lot size #3 (LongLotSize3) | LongLotSize3 — Long lot size #3 |
| Long lot size #4 (LongLotSize4) | LongLotSize4 — Long lot size #4 |
| Long lot size #5 (LongLotSize5) | LongLotSize5 — Long lot size #5 |
| Long lot size #6 (LongLotSize6) | LongLotSize6 — Long lot size #6 |
| Short take profit (ShortTakeProfit) | ShortTakeProfit — Short take profit |
| Short lot size #1 (ShortLotSize1) | ShortLotSize1 — Short lot size #1 |
| Short lot size #2 (ShortLotSize2) | ShortLotSize2 — Short lot size #2 |
| Short lot size #3 (ShortLotSize3) | ShortLotSize3 — Short lot size #3 |
| Short lot size #4 (ShortLotSize4) | ShortLotSize4 — Short lot size #4 |
| Short lot size #5 (ShortLotSize5) | ShortLotSize5 — Short lot size #5 |
| Short lot size #6 (ShortLotSize6) | ShortLotSize6 — Short lot size #6 |
| Distance, pips (distance) | distance — Distance, pips |
| Slippage, points (slippagePoints) | slippagePoints — Slippage, points |
| Magic number (magic_Number) | magic_Number — Magic number |
Поиск по коду файла
#property version "1.1"
#property strict
extern bool ManualMode = true; // Manual mode?
extern double InitialAmount = 0.1; // Initial amount
extern string GeneralSection = ""; // == General ==
extern double LongTakeProfit = 10; // Long take profit
extern double LongLotSize1 = 0.1; // Long lot size #1
extern double LongLotSize2 = 0.1; // Long lot size #2
extern double LongLotSize3 = 0.1; // Long lot size #3
extern double LongLotSize4 = 0.1; // Long lot size #4
extern double LongLotSize5 = 0.1; // Long lot size #5
extern double LongLotSize6 = 0.1; // Long lot size #6
extern double ShortTakeProfit = 10; // Short take profit
extern double ShortLotSize1 = 0.1; // Short lot size #1
extern double ShortLotSize2 = 0.1; // Short lot size #2
extern double ShortLotSize3 = 0.1; // Short lot size #3
extern double ShortLotSize4 = 0.1; // Short lot size #4
extern double ShortLotSize5 = 0.1; // Short lot size #5
extern double ShortLotSize6 = 0.1; // Short lot size #6
extern double distance = 10; // Distance, pips
extern int slippagePoints = 3; // Slippage, points
extern int magic_Number = 42; // Magic number
enum StopLimitType
{
StopLimitDoNotUse, // Do not use
StopLimitPercent, // Set in %
StopLimitPips, // Set in Pips
StopLimitDollar, // Set in $,
StopLimitRiskReward, // Set in % of stop loss
StopLimitAbsolute // Set in absolite value (rate)
};
enum OrderSide
{
BuySide,
SellSide
};
enum PositionSizeType
{
PositionSizeAmount, // $
PositionSizeContract, // In contracts
PositionSizeEquity, // % of equity
PositionSizeRisk // Risk in % of equity
};
class InstrumentInfo
{
string _symbol;
double _mult;
double _point;
double _pipSize;
int _digits;
double _tickSize;
public:
InstrumentInfo(const string symbol)
{
_symbol = symbol;
_point = MarketInfo(symbol, MODE_POINT);
_digits = (int)MarketInfo(symbol, MODE_DIGITS);
_mult = _digits == 3 || _digits == 5 ? 10 : 1;
_pipSize = _point * _mult;
_tickSize = MarketInfo(_symbol, MODE_TICKSIZE);
}
static double GetBid(const string symbol) { return MarketInfo(symbol, MODE_BID); }
double GetBid() { return GetBid(_symbol); }
static double GetAsk(const string symbol) { return MarketInfo(symbol, MODE_ASK); }
double GetAsk() { return GetAsk(_symbol); }
double GetPipSize() { return _pipSize; }
double GetPointSize() { return _point; }
string GetSymbol() { return _symbol; }
double GetSpread() { return (GetAsk() - GetBid()) / GetPipSize(); }
int GetDigits() { return _digits; }
double GetTickSize() { return _tickSize; }
double RoundRate(const double rate)
{
return NormalizeDouble(MathCeil(rate / _tickSize + 0.5) * _tickSize, _digits);
}
};
enum CompareType
{
CompareLessThan
};
class OrdersIterator
{
bool _useMagicNumber;
int _magicNumber;
bool _useOrderType;
int _orderType;
bool _trades;
bool _useSide;
bool _isBuySide;
int _lastIndex;
bool _useSymbol;
string _symbol;
bool _useProfit;
double _profit;
CompareType _profitCompare;
bool _orders;
public:
OrdersIterator()
{
_useOrderType = false;
_useMagicNumber = false;
_useSide = false;
_lastIndex = INT_MIN;
_trades = false;
_useSymbol = false;
_useProfit = false;
_orders = false;
}
OrdersIterator *WhenSymbol(const string symbol)
{
_useSymbol = true;
_symbol = symbol;
return &this;
}
OrdersIterator *WhenProfit(const double profit, const CompareType compare)
{
_useProfit = true;
_profit = profit;
_profitCompare = compare;
return &this;
}
OrdersIterator *WhenTrade()
{
_trades = true;
return &this;
}
OrdersIterator *WhenOrder()
{
_orders = true;
return &this;
}
OrdersIterator *WhenSide(const OrderSide side)
{
_useSide = true;
_isBuySide = side == BuySide;
return &this;
}
OrdersIterator *WhenOrderType(const int orderType)
{
_useOrderType = true;
_orderType = orderType;
return &this;
}
OrdersIterator *WhenMagicNumber(const int magicNumber)
{
_useMagicNumber = true;
_magicNumber = magicNumber;
return &this;
}
int GetOrderType() { return OrderType(); }
double GetProfit() { return OrderProfit(); }
double IsBuy() { return OrderType() == OP_BUY; }
double IsSell() { return OrderType() == OP_SELL; }
int Count()
{
int count = 0;
for (int i = OrdersTotal() - 1; i >= 0; i--)
{
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) && PassFilter())
{
count++;
}
}
return count;
}
bool Next()
{
if (_lastIndex == INT_MIN)
{
_lastIndex = OrdersTotal() - 1;
}
else
_lastIndex = _lastIndex - 1;
while (_lastIndex >= 0)
{
if (OrderSelect(_lastIndex, SELECT_BY_POS, MODE_TRADES) && PassFilter())
return true;
_lastIndex = _lastIndex - 1;
}
return false;
}
bool Any()
{
for (int i = OrdersTotal() - 1; i >= 0; i--)
{
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) && PassFilter())
{
return true;
}
}
return false;
}
private:
bool PassFilter()
{
if (_useMagicNumber && OrderMagicNumber() != _magicNumber)
return false;
if (_useOrderType && OrderType() != _orderType)
return false;
if (_trades && !IsTrade())
return false;
if (_orders && IsTrade())
return false;
if (_useSymbol && OrderSymbol() != _symbol)
return false;
if (_useProfit)
{
switch (_profitCompare)
{
case CompareLessThan:
if (OrderProfit() >= _profit)
return false;
break;
}
}
if (_useSide)
{
if (_trades)
{
if (_isBuySide && !IsBuy())
return false;
if (!_isBuySide && !IsSell())
return false;
}
else
{
}
}
return true;
}
bool IsTrade()
{
return (OrderType() == OP_BUY || OrderType() == OP_SELL) && OrderCloseTime() == 0.0;
}
};
class TradeCalculator
{
InstrumentInfo *_symbol;
TradeCalculator(const string symbol)
{
_symbol = new InstrumentInfo(symbol);
}
public:
static TradeCalculator *Create(const string symbol)
{
ResetLastError();
double temp = MarketInfo(symbol, MODE_POINT);
if (GetLastError() != 0)
return NULL;
return new TradeCalculator(symbol);
}
~TradeCalculator()
{
delete _symbol;
}
double GetPipSize() { return _symbol.GetPipSize(); }
string GetSymbol() { return _symbol.GetSymbol(); }
double GetBid() { return _symbol.GetBid(); }
double GetAsk() { return _symbol.GetAsk(); }
int GetDigits() { return _symbol.GetDigits(); }
double GetSpread() { return _symbol.GetSpread(); }
static bool IsBuyOrder()
{
switch (OrderType())
{
case OP_BUY:
case OP_BUYLIMIT:
case OP_BUYSTOP:
return true;
}
return false;
}
double GetBreakevenPrice(const int side, const int magicNumber, double &totalAmount)
{
totalAmount = 0.0;
double lotStep = SymbolInfoDouble(_symbol.GetSymbol(), SYMBOL_VOLUME_STEP);
double price = side == OP_BUY ? GetBid() : GetAsk();
double totalPL = 0;
OrdersIterator it1();
it1.WhenMagicNumber(magicNumber);
it1.WhenSymbol(_symbol.GetSymbol());
it1.WhenOrderType(side);
while (it1.Next())
{
double orderLots = OrderLots();
totalAmount += orderLots / lotStep;
if (side == OP_BUY)
totalPL += (price - OrderOpenPrice()) * (OrderLots() / lotStep);
else
totalPL += (OrderOpenPrice() - price) * (OrderLots() / lotStep);
}
if (totalAmount == 0.0)
return 0.0;
double shift = -(totalPL / totalAmount);
return side == OP_BUY ? price + shift : price - shift;
}
double CalculateTakeProfit(const bool isBuy, const double takeProfit, const StopLimitType takeProfitType, const double amount, double basePrice)
{
int direction = isBuy ? 1 : -1;
switch (takeProfitType)
{
case StopLimitPercent:
return RoundRate(basePrice + basePrice * takeProfit / 100.0 * direction);
case StopLimitPips:
return RoundRate(basePrice + takeProfit * _symbol.GetPipSize() * direction);
case StopLimitDollar:
return RoundRate(basePrice + CalculateSLShift(amount, takeProfit) * direction);
case StopLimitAbsolute:
return takeProfit;
}
return 0.0;
}
double CalculateStopLoss(const bool isBuy, const double stopLoss, const StopLimitType stopLossType, const double amount, double basePrice)
{
int direction = isBuy ? 1 : -1;
switch (stopLossType)
{
case StopLimitPercent:
return RoundRate(basePrice - basePrice * stopLoss / 100.0 * direction);
case StopLimitPips:
return RoundRate(basePrice - stopLoss * _symbol.GetPipSize() * direction);
case StopLimitDollar:
return RoundRate(basePrice - CalculateSLShift(amount, stopLoss) * direction);
case StopLimitAbsolute:
return stopLoss;
}
return 0.0;
}
double GetLots(PositionSizeType lotsType, double lotsValue, double stopDistance)
{
switch (lotsType)
{
case PositionSizeAmount:
return GetLotsForMoney(lotsValue);
case PositionSizeContract:
return LimitLots(RoundLots(lotsValue));
case PositionSizeEquity:
return GetLotsForMoney(AccountEquity() * lotsValue / 100.0);
case PositionSizeRisk:
{
double affordableLoss = AccountEquity() * lotsValue / 100.0;
double unitCost = MarketInfo(_symbol.GetSymbol(), MODE_TICKVALUE);
double tickSize = _symbol.GetTickSize();
double possibleLoss = unitCost * stopDistance / tickSize;
if (possibleLoss <= 0.01)
return 0;
return LimitLots(RoundLots(affordableLoss / possibleLoss));
}
}
return lotsValue;
}
bool IsLotsValid(const double lots, PositionSizeType lotsType, string &error)
{
switch (lotsType)
{
case PositionSizeContract:
return IsContractLotsValid(lots, error);
}
return true;
}
double NormalizeLots(const double lots)
{
return LimitLots(RoundLots(lots));
}
double RoundRate(const double rate)
{
return _symbol.RoundRate(rate);
}
private:
bool IsContractLotsValid(const double lots, string &error)
{
double minVolume = SymbolInfoDouble(_symbol.GetSymbol(), SYMBOL_VOLUME_MIN);
if (minVolume > lots)
{
error = "Min. allowed lot size is " + DoubleToString(minVolume);
return false;
}
double maxVolume = SymbolInfoDouble(_symbol.GetSymbol(), SYMBOL_VOLUME_MAX);
if (maxVolume < lots)
{
error = "Max. allowed lot size is " + DoubleToString(maxVolume);
return false;
}
return true;
}
double GetLotsForMoney(const double money)
{
double marginRequired = MarketInfo(_symbol.GetSymbol(), MODE_MARGINREQUIRED);
if (marginRequired <= 0.0)
{
Print("Margin is 0. Server misconfiguration?");
return 0.0;
}
double lots = RoundLots(money / marginRequired);
return LimitLots(lots);
}
double RoundLots(const double lots)
{
double lotStep = SymbolInfoDouble(_symbol.GetSymbol(), SYMBOL_VOLUME_STEP);
if (lotStep == 0)
return 0.0;
return floor(lots / lotStep) * lotStep;
}
double LimitLots(const double lots)
{
double minVolume = SymbolInfoDouble(_symbol.GetSymbol(), SYMBOL_VOLUME_MIN);
if (minVolume > lots)
return 0.0;
double maxVolume = SymbolInfoDouble(_symbol.GetSymbol(), SYMBOL_VOLUME_MAX);
if (maxVolume < lots)
return maxVolume;
return lots;
}
double CalculateSLShift(const double amount, const double money)
{
double unitCost = MarketInfo(_symbol.GetSymbol(), MODE_TICKVALUE);
double tickSize = _symbol.GetTickSize();
return (money / (unitCost / tickSize)) / amount;
}
};
class OrderBuilder
{
OrderSide _orderSide;
string _instrument;
double _amount;
double _rate;
int _slippage;
double _stop;
double _limit;
int _magicNumber;
string _comment;
public:
OrderBuilder *SetSide(const OrderSide orderSide)
{
_orderSide = orderSide;
return &this;
}
OrderBuilder *SetInstrument(const string instrument)
{
_instrument = instrument;
return &this;
}
OrderBuilder *SetAmount(const double amount)
{
_amount = amount;
return &this;
}
OrderBuilder *SetRate(const double rate)
{
_rate = NormalizeDouble(rate, Digits);
return &this;
}
OrderBuilder *SetSlippage(const int slippage)
{
_slippage = slippage;
return &this;
}
OrderBuilder *SetStopLoss(const double stop)
{
_stop = NormalizeDouble(stop, Digits);
return &this;
}
OrderBuilder *SetTakeProfit(const double limit)
{
_limit = NormalizeDouble(limit, Digits);
return &this;
}
OrderBuilder *SetMagicNumber(const int magicNumber)
{
_magicNumber = magicNumber;
return &this;
}
OrderBuilder *SetComment(const string comment)
{
_comment = comment;
return &this;
}
int Execute(string &errorMessage)
{
int orderType;
if (_orderSide == BuySide)
Показано первые 50% кода (символов: 19105)
Открыть по тарифу
Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.
Разовая покупка файла
На этой странице откроется полный исходный код файла вместо ознакомительного фрагмента.
Зачем нужен email? После подтверждения оплаты файл сохранится в кабинете на этот email. Если аккаунта ещё нет, мы создадим его и пришлём ссылку для задания пароля. Если аккаунт уже есть, покупка добавится в него. Укажите адрес, к которому у вас есть доступ.
Чтобы оформить заказ, введите email и перейдите к оплате.