mql5/Include/MasterOfPuppetsLib/Utils.mqh

168 lines
6 KiB
MQL5
Raw Permalink Normal View History

2026-03-03 01:41:15 +03:00
//+------------------------------------------------------------------+
//| 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
2026-03-06 09:18:39 +03:00
#include <Trade\PositionInfo.mqh>
2026-03-06 04:15:42 +03:00
#include <MasterOfPuppetsLib\Actions.mqh>
2026-03-03 01:47:50 +03:00
#include <MasterOfPuppetsLib\DuplicateFinder.mqh>
2026-03-03 01:41:15 +03:00
#property copyright "Copyright 2026, MasterOfPuppets"
#property link "https://forge.mql5.io/masterofpuppets/mql5"
2026-03-06 09:18:39 +03:00
//+------------------------------------------------------------------+
//| Positions initialization function |
//+------------------------------------------------------------------+
void InitPositions(CPositionInfo &srcPositionInfo)
{
ulong allPositionsTickets[];
int positionsTotal = PositionsTotal();
Print("positionsTotal: ", positionsTotal);
ArrayFree(allPositionsTickets);
ArrayResize(allPositionsTickets, positionsTotal);
for(int i = 0; i < positionsTotal; i++)
{
if(srcPositionInfo.SelectByIndex(i))
{
allPositionsTickets[i] = srcPositionInfo.Ticket();
}
}
ArrayPrint(allPositionsTickets);
}
2026-03-03 01:47:50 +03:00
//+------------------------------------------------------------------+
//| Is key mapping correct function |
//+------------------------------------------------------------------+
2026-03-04 21:54:50 +03:00
template<typename T>
bool IsKeyMappingCorrect(Actions<T> &actionsObject)
2026-03-03 01:47:50 +03:00
{
int actionKeys[];
2026-03-04 21:54:50 +03:00
actionsObject.GetActionKeys(actionKeys);
2026-03-03 01:47:50 +03:00
string actionNames[];
2026-03-04 21:54:50 +03:00
actionsObject.GetActionNames(actionNames);
2026-03-03 01:47:50 +03:00
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]];
}
2026-03-04 21:54:50 +03:00
error += StringFormat("Error: duplicated key [%c] for %s\n", (uchar) duplicateResults[i].value, mappedActionNames);
2026-03-03 01:47:50 +03:00
}
Alert(error);
return false;
}
2026-03-03 01:41:15 +03:00
//+------------------------------------------------------------------+
//| Is standard deal reason function |
//+------------------------------------------------------------------+
2026-03-05 02:13:29 +03:00
bool IsStandardDealReason(const int dealReason)
2026-03-03 01:41:15 +03:00
{
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)
{
2026-03-04 21:38:42 +03:00
return MathAbs(value) < DBL_EPSILON;
2026-03-03 01:41:15 +03:00
}
//+------------------------------------------------------------------+
//| Play sound file function |
//+------------------------------------------------------------------+
2026-03-05 02:13:29 +03:00
void PlaySoundFile(const bool soundEnabled, const string soundFileName)
2026-03-03 01:41:15 +03:00
{
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);
2026-03-04 22:09:38 +03:00
request.tp = PositionGetDouble(POSITION_TP);
2026-03-03 01:41:15 +03:00
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);
2026-03-04 22:09:38 +03:00
request.tp = PositionGetDouble(POSITION_TP);
2026-03-03 01:41:15 +03:00
if(OrderSend(request, result))
{
};
}
}
}
}
}
}
#endif
//+------------------------------------------------------------------+