1
0
Fourche 0
bifurqué depuis masterofpuppets/mql5
mql5/Include/MasterOfPuppetsLib/Utils.mqh
2026-03-03 01:47:50 +03:00

143 lignes
5,1 Kio
MQL5

//+------------------------------------------------------------------+
//| Utils.mqh |
//| Copyright 2026, MasterOfPuppets |
//| https://forge.mql5.io/masterofpuppets/mql5 |
//+------------------------------------------------------------------+
#ifndef MASTER_OF_PUPPETS_LIB_UTILS_MQH
#define MASTER_OF_PUPPETS_LIB_UTILS_MQH
#include <MasterOfPuppetsLib\DuplicateFinder.mqh>
#property copyright "Copyright 2026, MasterOfPuppets"
#property link "https://forge.mql5.io/masterofpuppets/mql5"
//+------------------------------------------------------------------+
//| Is key mapping correct function |
//+------------------------------------------------------------------+
bool IsKeyMappingCorrect()
{
int actionKeys[];
actions.GetActionKeys(actionKeys);
string actionNames[];
actions.GetActionNames(actionNames);
DuplicateResult<int> duplicateResults[];
DuplicateFinder<int>::Find(actionKeys, duplicateResults);
if(duplicateResults.Size() == 0)
{
return true;
}
string error;
for(uint i = 0; i < duplicateResults.Size(); i++)
{
string mappedActionNames;
for(uint j = 0; j < duplicateResults[i].indices.Size(); j++)
{
if(j > 0)
{
mappedActionNames += ", ";
}
mappedActionNames += actionNames[duplicateResults[i].indices[j]];
}
error += StringFormat("Error: duplicated key [%c] for %s\n", duplicateResults[i].value, mappedActionNames);
}
Alert(error);
return false;
}
//+------------------------------------------------------------------+
//| Is standard deal reason function |
//+------------------------------------------------------------------+
bool IsStandardDealReason(int dealReason)
{
switch(dealReason)
{
case DEAL_REASON_CLIENT:
case DEAL_REASON_EXPERT:
case DEAL_REASON_MOBILE:
case DEAL_REASON_SL:
case DEAL_REASON_TP:
case DEAL_REASON_WEB:
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| Is zero function |
//+------------------------------------------------------------------+
bool IsZero(const double value)
{
return MathAbs(value) < DBL_EPSILON ? true : false;
}
//+------------------------------------------------------------------+
//| Play sound file function |
//+------------------------------------------------------------------+
void PlaySoundFile(bool soundEnabled, string soundFileName)
{
if(soundEnabled)
{
PlaySound(soundFileName);
}
}
//+------------------------------------------------------------------+
//| Trailing stop function |
//+------------------------------------------------------------------+
//OnTick() TrailingStep
void TrailingStop(const int distance)
{
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
double trailingStep = distance * point;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(PositionSelectByTicket(ticket))
{
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
double currentSL = PositionGetDouble(POSITION_SL);
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
// Для покупок (Buy)
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
{
if(bid - openPrice > trailingStep) // Проверяем, в прибыли ли мы
{
if(currentSL < bid - trailingStep)
{
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_SLTP;
request.position = ticket;
request.sl = NormalizeDouble(bid - trailingStep, _Digits);
if(OrderSend(request, result))
{
};
}
}
}
// Для продаж (Sell)
else
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
{
if(openPrice - ask > trailingStep)
{
if(currentSL > ask + trailingStep || currentSL == 0)
{
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_SLTP;
request.position = ticket;
request.sl = NormalizeDouble(ask + trailingStep, _Digits);
if(OrderSend(request, result))
{
};
}
}
}
}
}
}
#endif
//+------------------------------------------------------------------+