mql5/Experts/MasterOfPuppets/Robot/Robot.mq5
MasterOfPuppets c61960286b add Robot()
2026-03-12 04:50:58 +03:00

604 Zeilen
23 KiB
MQL5

//+------------------------------------------------------------------+
//| Robot.mq5 |
//| Copyright 2026, MasterOfPuppets |
//| https://forge.mql5.io/masterofpuppets/mql5 |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Includes |
//+------------------------------------------------------------------+
#include <Trade\DealInfo.mqh>
#include <Trade\OrderInfo.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\SymbolInfo.mqh>
#include <Trade\Trade.mqh>
#include <MasterOfPuppetsLib\Modifiers\ClosePositionModifier.mqh>
#include <MasterOfPuppetsLib\Modifiers\DefendModifier.mqh>
#include <MasterOfPuppetsLib\Modifiers\ProtectModifier.mqh>
#include <MasterOfPuppetsLib\ActionKey.mqh>
#include <MasterOfPuppetsLib\Actions.mqh>
#include <MasterOfPuppetsLib\DuplicateFinder.mqh>
#include <MasterOfPuppetsLib\GeneratorsDefinition.mqh>
#include <MasterOfPuppetsLib\Reporter.mqh>
#include <MasterOfPuppetsLib\TradeAction.mqh>
#include <MasterOfPuppetsLib\TradeContext.mqh>
#include <MasterOfPuppetsLib\Trader.mqh>
#include <MasterOfPuppetsLib\TraderContext.mqh>
#include <MasterOfPuppetsLib\Utils.mqh>
#include "Action.mqh"
//+------------------------------------------------------------------+
//| Properties |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, MasterOfPuppets"
#property description "Advanced Position Builder, Pyramider && Scalper Terminal"
#property link "https://forge.mql5.io/masterofpuppets/mql5"
#property version "1.00"
//+------------------------------------------------------------------+
//| Inputs |
//+------------------------------------------------------------------+
input bool ASYNC_MODE_ENABLED = false;
input double CONTRACTS = 0.01;
input int INDENT_SIZE = 134;
input int LAST_PROFITS_SIZE = 10;
input bool SOUND_ENABLED = true;
input string SOUND_FILE_NAME = "ok.wav";
input double STOP_LOSS = 1.0;
input double TAKE_PROFIT = 0.0;
input group "Action keys"
MASTER_OF_PUPPETS_ACTION_KEY_MAPPINGS(MASTER_OF_PUPPETS_LIB_GENERATE_INPUT)
//+------------------------------------------------------------------+
//| Constants |
//+------------------------------------------------------------------+
const string INDENT_FORMAT = StringFormat("%%%is\n", INDENT_SIZE);
const ulong MAGIC = 202603110245;
//+------------------------------------------------------------------+
//| Variables |
//+------------------------------------------------------------------+
Actions<Action> actions;
string actionsUsage;
bool buyPyramid = false;
CDealInfo dealInfo;
string lastProfitInfo;
COrderInfo orderInfo;
CPositionInfo positionInfo;
Reporter reporter;
bool sellPyramid = false;
CSymbolInfo symbolInfo;
CTrade trade;
TradeContext tradeContext;
Trader trader;
TraderContext traderContext;
ClosePositionModifier closeAllPositionModifier;
ClosePositionModifier closeExpertPositionModifier;
DefendModifier defendAllModifier;
DefendModifier defendExpertModifier;
ProtectModifier protectModifier;
datetime lastBarTime;
//+------------------------------------------------------------------+
//| ChartEvent function |
//+------------------------------------------------------------------+
void OnChartEvent(const int32_t id, const long &lparam, const double &dparam, const string &sparam)
{
if(id != CHARTEVENT_KEYDOWN)
{
return;
}
Action action = (Action) actions.GetAction(lparam);
switch(action)
{
MASTER_OF_PUPPETS_ACTION_KEY_MAPPINGS(MASTER_OF_PUPPETS_LIB_GENERATE_CASE)
}
}
//+------------------------------------------------------------------+
//| On buy function |
//+------------------------------------------------------------------+
void OnBUY(const Action action)
{
trader.PositionOpen(actions.GetActionName(action), TradeAction::TRADE_ACTION_BUY);
}
//+------------------------------------------------------------------+
//| On buy limit function |
//+------------------------------------------------------------------+
void OnBUY_LIMIT(const Action action)
{
trader.OrderOpen(actions.GetActionName(action), TradeAction::TRADE_ACTION_BUY_LIMIT);
}
//+------------------------------------------------------------------+
//| On buy protect function |
//+------------------------------------------------------------------+
void OnBUY_PROTECT(const Action action)
{
trader.Modify(actions.GetActionName(action), &protectModifier);
OnBUY(action);
}
//+------------------------------------------------------------------+
//| On buy pyramid function |
//+------------------------------------------------------------------+
void OnBUY_PYRAMID(const Action action)
{
buyPyramid = true;
OnBUY(action);
}
//+------------------------------------------------------------------+
//| On buy stop function |
//+------------------------------------------------------------------+
void OnBUY_STOP(const Action action)
{
trader.OrderOpen(actions.GetActionName(action), TradeAction::TRADE_ACTION_BUY_STOP);
}
//+------------------------------------------------------------------+
//| On close all positions function |
//+------------------------------------------------------------------+
void OnCLOSE_ALL_POSITIONS(const Action action)
{
trader.Modify(actions.GetActionName(action), &closeAllPositionModifier);
}
//+------------------------------------------------------------------+
//| On close expert positions function |
//+------------------------------------------------------------------+
void OnCLOSE_EXPERT_POSITIONS(const Action action)
{
trader.Modify(actions.GetActionName(action), &closeExpertPositionModifier);
}
//+------------------------------------------------------------------+
//| On defend all positions function |
//+------------------------------------------------------------------+
void OnDEFEND_ALL_POSITIONS(const Action action)
{
trader.Modify(actions.GetActionName(action), &defendAllModifier);
}
//+------------------------------------------------------------------+
//| On defend expert positions function |
//+------------------------------------------------------------------+
void OnDEFEND_EXPERT_POSITIONS(const Action action)
{
trader.Modify(actions.GetActionName(action), &defendExpertModifier);
}
//+------------------------------------------------------------------+
//| On delete all orders function |
//+------------------------------------------------------------------+
void OnDELETE_ALL_ORDERS(const Action action)
{
trader.DeleteOrders(actions.GetActionName(action), true);
}
//+------------------------------------------------------------------+
//| On delete expert orders function |
//+------------------------------------------------------------------+
void OnDELETE_EXPERT_ORDERS(const Action action)
{
trader.DeleteOrders(actions.GetActionName(action), false);
}
//+------------------------------------------------------------------+
//| On exit master of puppets function |
//+------------------------------------------------------------------+
void OnEXIT_MASTER_OF_PUPPETS(const Action action)
{
Print(actions.GetActionName(action));
PlaySoundFile(SOUND_ENABLED, SOUND_FILE_NAME);
ExpertRemove();
}
//+------------------------------------------------------------------+
//| On lock function |
//+------------------------------------------------------------------+
void OnLOCK(const Action action)
{
OnBUY(action);
OnSELL(action);
}
//+------------------------------------------------------------------+
//| On reverse all positions function |
//+------------------------------------------------------------------+
void OnREVERSE_ALL_POSITIONS(const Action action)
{
ReversePositions(true);
}
//+------------------------------------------------------------------+
//| On reverse expert positions function |
//+------------------------------------------------------------------+
void OnREVERSE_EXPERT_POSITIONS(const Action action)
{
ReversePositions(false);
}
//+------------------------------------------------------------------+
//| Reverse positions function |
//+------------------------------------------------------------------+
void ReversePositions(const bool allPositions)
{
Action action;
if(allPositions)
{
action = Action::DO_REVERSE_ALL_POSITIONS;
}
else
{
action = Action::DO_REVERSE_EXPERT_POSITIONS;
}
Print(actions.GetActionName(action));
if(positionInfo.SelectByIndex(0))
{
switch(positionInfo.PositionType())
{
case ENUM_POSITION_TYPE::POSITION_TYPE_BUY:
action = Action::DO_SELL;
break;
case ENUM_POSITION_TYPE::POSITION_TYPE_SELL:
action = Action::DO_BUY;
break;
}
}
else
{
PlaySoundFile(SOUND_ENABLED, SOUND_FILE_NAME);
return;
}
if(allPositions)
{
OnCLOSE_ALL_POSITIONS(Action::DO_CLOSE_ALL_POSITIONS);
}
else
{
OnCLOSE_EXPERT_POSITIONS(Action::DO_CLOSE_EXPERT_POSITIONS);
}
switch(action)
{
case Action::DO_BUY:
trader.PositionOpen(actions.GetActionName(action), TradeAction::TRADE_ACTION_BUY);
break;
case Action::DO_SELL:
trader.PositionOpen(actions.GetActionName(action), TradeAction::TRADE_ACTION_SELL);
break;
}
}
//+------------------------------------------------------------------+
//| On sell function |
//+------------------------------------------------------------------+
void OnSELL(const Action action)
{
trader.PositionOpen(actions.GetActionName(action), TradeAction::TRADE_ACTION_SELL);
}
//+------------------------------------------------------------------+
//| On sell limit function |
//+------------------------------------------------------------------+
void OnSELL_LIMIT(const Action action)
{
trader.OrderOpen(actions.GetActionName(action), TradeAction::TRADE_ACTION_SELL_LIMIT);
}
//+------------------------------------------------------------------+
//| On sell protect function |
//+------------------------------------------------------------------+
void OnSELL_PROTECT(const Action action)
{
trader.Modify(actions.GetActionName(action), &protectModifier);
OnSELL(action);
}
//+------------------------------------------------------------------+
//| On sell pyramid function |
//+------------------------------------------------------------------+
void OnSELL_PYRAMID(const Action action)
{
sellPyramid = true;
OnSELL(action);
}
//+------------------------------------------------------------------+
//| On sell stop function |
//+------------------------------------------------------------------+
void OnSELL_STOP(const Action action)
{
trader.OrderOpen(actions.GetActionName(action), TradeAction::TRADE_ACTION_SELL_STOP);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
EventKillTimer();
}
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
if(!symbolInfo.Name(_Symbol))
{
PlaySoundFile(SOUND_ENABLED, SOUND_FILE_NAME);
return(INIT_FAILED);
}
InitActions();
if(!IsKeyMappingCorrect(actions))
{
PlaySoundFile(SOUND_ENABLED, SOUND_FILE_NAME);
return(INIT_PARAMETERS_INCORRECT);
}
EventSetTimer(1);
trade.SetAsyncMode(ASYNC_MODE_ENABLED);
trade.SetExpertMagicNumber(MAGIC);
tradeContext.Init(GetPointer(orderInfo), GetPointer(positionInfo), GetPointer(symbolInfo), GetPointer(trade));
traderContext.Init(CONTRACTS, SOUND_ENABLED, SOUND_FILE_NAME, STOP_LOSS, TAKE_PROFIT, MAGIC);
trader.Init(GetPointer(tradeContext), GetPointer(traderContext));
closeAllPositionModifier.Init(GetPointer(tradeContext), GetPointer(traderContext));
closeExpertPositionModifier.Init(GetPointer(tradeContext), GetPointer(traderContext), true);
defendAllModifier.Init(GetPointer(tradeContext), GetPointer(traderContext));
defendExpertModifier.Init(GetPointer(tradeContext), GetPointer(traderContext), true);
protectModifier.Init(GetPointer(tradeContext), GetPointer(traderContext));
reporter.Init(GetPointer(dealInfo), LAST_PROFITS_SIZE);
InitLastProfits();
actionsUsage = actions.Usage();
Print(actionsUsage);
lastBarTime = iTime(_Symbol, _Period, 0);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Actions initialization function |
//+------------------------------------------------------------------+
void InitActions()
{
actions.Clear();
MASTER_OF_PUPPETS_ACTION_KEY_MAPPINGS(MASTER_OF_PUPPETS_LIB_GENERATE_ADD_ACTION)
}
//+------------------------------------------------------------------+
//| Last profits initialization function |
//+------------------------------------------------------------------+
void InitLastProfits()
{
reporter.InitLastProfits();
SetLastProfit();
}
//+------------------------------------------------------------------+
//| Set last profit function |
//+------------------------------------------------------------------+
void SetLastProfit()
{
lastProfitInfo = "\n";
const CArrayObj *lastProfits = reporter.GetLastProfits();
for(int i = lastProfits.Total() - 1; i >= 0; i--)
{
LastProfit *lastProfit = lastProfits.At(i);
lastProfitInfo += StringFormat(INDENT_FORMAT,
lastProfit.message + lastProfit.suffix + StringFormat("%-7.2f", lastProfit.profit));
}
lastProfitInfo += StringFormat(INDENT_FORMAT, DoubleToString(reporter.GetTotalLastProfit(), 2));
}
//+------------------------------------------------------------------+
//| Tick function |
//+------------------------------------------------------------------+
void OnTick()
{
BuildPyramid();
Robot();
}
//+------------------------------------------------------------------+
//| Build pyramid function |
//+------------------------------------------------------------------+
void BuildPyramid()
{
if(!(buyPyramid || sellPyramid))
{
return;
}
symbolInfo.RefreshRates();
if(buyPyramid && (symbolInfo.Ask() > trader.GetBuyPyramidPriceOpen() + STOP_LOSS))
{
OnDEFEND_ALL_POSITIONS(Action::UNKNOWN);
OnBUY(Action::DO_BUY);
}
if(sellPyramid && (symbolInfo.Bid() < trader.GetSellPyramidPriceOpen() - STOP_LOSS))
{
OnDEFEND_ALL_POSITIONS(Action::UNKNOWN);
OnSELL(Action::DO_SELL);
}
}
//+------------------------------------------------------------------+
//| Robot lock function |
//+------------------------------------------------------------------+
void RobotLock()
{
datetime currentBarTime = iTime(_Symbol, _Period, 0);
if(currentBarTime != lastBarTime)
{
OnCLOSE_EXPERT_POSITIONS(Action::DO_CLOSE_EXPERT_POSITIONS);
OnLOCK(Action::DO_LOCK);
lastBarTime = currentBarTime;
}
}
input int WaitSeconds = 10; // Сколько секунд ждем после открытия бара
input double MinReflected = 10.0; // Минимальный откат (в пунктах), чтобы считать сигнал валидным
bool signalProcessed = false;
double initialOpen = 0;
double extremePoint = 0; // Самая дальняя точка за первые 10 сек
input int InpWaitSeconds = 10; // Сколько секунд ждать от начала свечи
input double InpMinSize = 10.0; // Минимальный размер свечи в пунктах для входа
//+------------------------------------------------------------------+
//| Robot function |
//+------------------------------------------------------------------+
void Robot()
{
//static datetime lastBarTime = 0;
static bool isAnalyzed = false;
datetime currentTime = TimeCurrent();
datetime barStartTime = iTime(_Symbol, PERIOD_M1, 0);
// Если началась новая минута — сбрасываем флаг анализа
if(barStartTime != lastBarTime)
{
OnCLOSE_EXPERT_POSITIONS(Action::DO_CLOSE_EXPERT_POSITIONS);
lastBarTime = barStartTime;
isAnalyzed = false;
}
// Проверяем, прошло ли нужное количество секунд
int secondsPassed = (int)(currentTime - barStartTime);
if(!isAnalyzed && secondsPassed >= InpWaitSeconds)
{
double high = iHigh(_Symbol, PERIOD_M1, 0);
double low = iLow(_Symbol, PERIOD_M1, 0);
double current = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double distToLow = current - low;
double distToHigh = high - current;
// Проверка на минимальную волатильность (чтобы не торговать на доджи)
if((high - low) / _Point < InpMinSize)
{
isAnalyzed = true;
return;
}
double prevOpen = iOpen(_Symbol, PERIOD_M1, 1);
double prevClose = iClose(_Symbol, PERIOD_M1, 1);
Print("prevOpen: ", NormalizeDouble(prevOpen, _Digits), " prevClose: ", NormalizeDouble(prevClose, _Digits),
" prevClose - prevOpen: ", NormalizeDouble(prevClose - prevOpen, _Digits));
Print("\nlow: ", NormalizeDouble(low, _Digits), " current: ", NormalizeDouble(current, _Digits),
" high: ", NormalizeDouble(high, _Digits));
if(distToLow > distToHigh)
{
OnBUY(Action::DO_BUY);
Print("Прогноз: ВВЕРХ. (Отрезок снизу ", NormalizeDouble(distToLow / _Point, _Digits), " пт > сверху ",
NormalizeDouble(distToHigh / _Point, _Digits), " пт)");
}
else
if(distToHigh > distToLow)
{
OnSELL(Action::DO_SELL);
Print("Прогноз: ВНИЗ. (Отрезок сверху ", NormalizeDouble(distToHigh / _Point, _Digits), " пт > снизу ",
NormalizeDouble(distToLow / _Point, _Digits), " пт)");
}
isAnalyzed = true; // Чтобы не частить в рамках одной минуты
}
}
//+------------------------------------------------------------------+
//| Robot1 function |
//+------------------------------------------------------------------+
void Robot1()
{
datetime currentBarTime = iTime(_Symbol, PERIOD_M1, 0);
// Проверка начала нового бара
if(currentBarTime != lastBarTime)
{
lastBarTime = currentBarTime;
signalProcessed = false;
initialOpen = iOpen(_Symbol, PERIOD_M1, 0);
extremePoint = initialOpen;
}
if(signalProcessed)
return;
int secondsElapsed = (int)(TimeCurrent() - currentBarTime);
// Фаза 1: Собираем экстремумы в первые 10 секунд
if(secondsElapsed < WaitSeconds)
{
double currentBid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
if(currentBid > extremePoint)
extremePoint = currentBid;
if(currentBid < extremePoint)
extremePoint = currentBid;
}
// Фаза 2: После 10 секунд ищем пересечение цены открытия
else
{
double currentBid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double pointsShift = MathAbs(extremePoint - initialOpen) / _Point;
// Условие: цена была НИЖЕ открытия, а теперь пробила его ВВЕРХ
if(extremePoint < initialOpen && currentBid > initialOpen && pointsShift >= MinReflected)
{
Print("Сигнал ВВЕРХ: Цена откатилась от минимума на ", pointsShift, " пт.");
signalProcessed = true;
// Здесь код для открытия сделки Buy
}
// Условие: цена была ВЫШЕ открытия, а теперь пробила его ВНИЗ
if(extremePoint > initialOpen && currentBid < initialOpen && pointsShift >= MinReflected)
{
Print("Сигнал ВНИЗ: Цена откатилась от максимума на ", pointsShift, " пт.");
signalProcessed = true;
// Здесь код для открытия сделки Sell
}
}
}
//+------------------------------------------------------------------+
//| Timer function |
//+------------------------------------------------------------------+
void OnTimer()
{
string comment = StringFormat(INDENT_FORMAT, TimeToString(TimeLocal(), TIME_MINUTES | TIME_SECONDS));
comment += lastProfitInfo;
comment += actionsUsage;
Comment(comment);
}
//+------------------------------------------------------------------+
//| Trade transaction function |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
const MqlTradeRequest &request,
const MqlTradeResult &result)
{
if(trans.type != TRADE_TRANSACTION_DEAL_ADD)
{
return;
}
InitLastProfits();
PlaySoundFile(SOUND_ENABLED, SOUND_FILE_NAME);
}
#include <MasterOfPuppetsLib\GeneratorsUndefinition.mqh>
#undef MASTER_OF_PUPPETS_ACTION_KEY_MAPPINGS
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| ToDo |
//| - error processing |
//| - objects |
//+------------------------------------------------------------------+