geforkt von masterofpuppets/mql5
698 Zeilen
25 KiB
MQL5
698 Zeilen
25 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| MasterOfPuppets.mq5 |
|
|
//| Copyright 2026, MasterOfPuppets |
|
|
//| https://forge.mql5.io/masterofpuppets/mql5 |
|
|
//+------------------------------------------------------------------+
|
|
//+------------------------------------------------------------------+
|
|
//| Includes |
|
|
//+------------------------------------------------------------------+
|
|
#include <Trade\PositionInfo.mqh>
|
|
#include <Trade\SymbolInfo.mqh>
|
|
#include <Trade\Trade.mqh>
|
|
#include <MasterOfPuppetsLib\ActionKey.mqh>
|
|
#include <MasterOfPuppetsLib\Actions.mqh>
|
|
#include <MasterOfPuppetsLib\DuplicateFinder.mqh>
|
|
#include <MasterOfPuppetsLib\TradeContext.mqh>
|
|
#include <MasterOfPuppetsLib\Utils.mqh>
|
|
#include "Action.mqh"
|
|
#include "ClosePositionModifier.mq5"
|
|
#include "DefendModifier.mq5"
|
|
#include "ProtectModifier.mq5"
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 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 = 7.0;
|
|
input double TAKE_PROFIT = 0.0;
|
|
input group "Action keys"
|
|
input ActionKey buyActionKey = B; // BUY
|
|
input ActionKey buyLimitActionKey = I; // BUY_LIMIT
|
|
input ActionKey buyProtectActionKey = O; // BUY_PROTECT
|
|
input ActionKey buyPyramidActionKey = M; // BUY_PYRAMID
|
|
input ActionKey buyStopActionKey = Y; // BUY_STOP
|
|
input ActionKey closeAllPositionsActionKey = Q; // CLOSE_ALL_POSITIONS
|
|
input ActionKey closeExpertPositionsActionKey = C; // CLOSE_EXPERT_POSITIONS
|
|
input ActionKey defendAllPositionsActionKey = F; // DEFEND_ALL_POSITIONS
|
|
input ActionKey defendExpertPositionsActionKey = D; // DEFEND_EXPERT_POSITIONS
|
|
input ActionKey exitScalperActionKey = E; // EXIT_SCALPER
|
|
input ActionKey lockActionKey = L; // LOCK
|
|
input ActionKey reverseAllPositionsActionKey = A; // REVERSE_ALL_POSITIONS
|
|
input ActionKey reverseExpertPositionsActionKey = R; // REVERSE_EXPERT_POSITIONS
|
|
input ActionKey sellActionKey = S; // SELL
|
|
input ActionKey sellLimitActionKey = T; // SELL_LIMIT
|
|
input ActionKey sellProtectActionKey = X; // SELL_PROTECT
|
|
input ActionKey sellPyramidActionKey = Z; // SELL_PYRAMID
|
|
input ActionKey sellStopActionKey = P; // SELL_STOP
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Constants |
|
|
//+------------------------------------------------------------------+
|
|
const string INDENT_FORMAT = StringFormat("%%%is\n", INDENT_SIZE);
|
|
const ulong MAGIC = 1234567;
|
|
const string MESSAGE_BUY = "BUY ";
|
|
const string MESSAGE_SELL = "SELL ";
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Structs |
|
|
//+------------------------------------------------------------------+
|
|
struct LastProfit
|
|
{
|
|
string message;
|
|
double profit;
|
|
string suffix;
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Variables |
|
|
//+------------------------------------------------------------------+
|
|
Actions<Action> actions;
|
|
string actionsUsage;
|
|
bool buyPyramid = false;
|
|
double buyPyramidPriceOpen;
|
|
string lastProfit;
|
|
LastProfit lastProfits[];
|
|
CPositionInfo positionInfo;
|
|
bool sellPyramid = false;
|
|
double sellPyramidPriceOpen;
|
|
CSymbolInfo symbolInfo;
|
|
double totalLastProfit;
|
|
CTrade trade;
|
|
TradeContext tradeContext;
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| ChartEvent function |
|
|
//+------------------------------------------------------------------+
|
|
void OnChartEvent(const int32_t id, const long &lparam, const double &dparam, const string &sparam)
|
|
{
|
|
if(id != CHARTEVENT_KEYDOWN)
|
|
{
|
|
return;
|
|
}
|
|
switch(actions.GetAction(lparam))
|
|
{
|
|
case Action::BUY:
|
|
Buy();
|
|
break;
|
|
case Action::BUY_LIMIT:
|
|
BuyLimit();
|
|
break;
|
|
case Action::BUY_PROTECT:
|
|
BuyProtect();
|
|
break;
|
|
case Action::BUY_PYRAMID:
|
|
BuyPyramid();
|
|
break;
|
|
case Action::BUY_STOP:
|
|
BuyStop();
|
|
break;
|
|
case Action::CLOSE_ALL_POSITIONS:
|
|
CloseAllPositions();
|
|
break;
|
|
case Action::CLOSE_EXPERT_POSITIONS:
|
|
CloseExpertPositions();
|
|
break;
|
|
case Action::DEFEND_ALL_POSITIONS:
|
|
DefendAllPositions();
|
|
break;
|
|
case Action::DEFEND_EXPERT_POSITIONS:
|
|
DefendExpertPositions();
|
|
break;
|
|
case Action::EXIT_SCALPER:
|
|
ExpertRemove();
|
|
PlaySoundFile(SOUND_ENABLED, SOUND_FILE_NAME);
|
|
break;
|
|
case Action::LOCK:
|
|
Buy();
|
|
Sell();
|
|
break;
|
|
case Action::REVERSE_ALL_POSITIONS:
|
|
ReverseAllPositions();
|
|
break;
|
|
case Action::REVERSE_EXPERT_POSITIONS:
|
|
ReverseExpertPositions();
|
|
break;
|
|
case Action::SELL:
|
|
Sell();
|
|
break;
|
|
case Action::SELL_LIMIT:
|
|
SellLimit();
|
|
break;
|
|
case Action::SELL_PROTECT:
|
|
SellProtect();
|
|
break;
|
|
case Action::SELL_PYRAMID:
|
|
SellPyramid();
|
|
break;
|
|
case Action::SELL_STOP:
|
|
SellStop();
|
|
break;
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Buy function |
|
|
//+------------------------------------------------------------------+
|
|
void Buy()
|
|
{
|
|
PositionOpen(Action::BUY);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Buy limit function |
|
|
//+------------------------------------------------------------------+
|
|
void BuyLimit()
|
|
{
|
|
OrderOpen(Action::BUY_LIMIT);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Buy protect function |
|
|
//+------------------------------------------------------------------+
|
|
void BuyProtect()
|
|
{
|
|
ProtectModifier protectModifier(GetPointer(tradeContext));
|
|
Modify(EnumToString(Action::BUY_PROTECT), &protectModifier);
|
|
Buy();
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Buy pyramid function |
|
|
//+------------------------------------------------------------------+
|
|
void BuyPyramid()
|
|
{
|
|
buyPyramid = true;
|
|
PositionOpen(Action::BUY);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Buy stop function |
|
|
//+------------------------------------------------------------------+
|
|
void BuyStop()
|
|
{
|
|
OrderOpen(Action::BUY_STOP);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Add last profit function |
|
|
//+------------------------------------------------------------------+
|
|
void AddLastProfit(const LastProfit &lastProfitStruct)
|
|
{
|
|
if(lastProfits.Size() == LAST_PROFITS_SIZE)
|
|
{
|
|
ArrayRemove(lastProfits, 0, 1);
|
|
}
|
|
ArrayResize(lastProfits, lastProfits.Size() + 1);
|
|
lastProfits[lastProfits.Size() - 1] = lastProfitStruct;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Calculate total last profit function |
|
|
//+------------------------------------------------------------------+
|
|
void CalculateTotalLastProfit()
|
|
{
|
|
totalLastProfit = 0.0;
|
|
for(uint i = 0; i < lastProfits.Size(); i++)
|
|
{
|
|
totalLastProfit += lastProfits[i].profit;
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Set last profit function |
|
|
//+------------------------------------------------------------------+
|
|
void SetLastProfit()
|
|
{
|
|
lastProfit = "\n";
|
|
for(uint i = 0; i < lastProfits.Size(); i++)
|
|
{
|
|
lastProfit += StringFormat(INDENT_FORMAT,
|
|
lastProfits[i].message + lastProfits[i].suffix + StringFormat("%-7.2f", lastProfits[i].profit));
|
|
}
|
|
lastProfit += StringFormat(INDENT_FORMAT, DoubleToString(totalLastProfit, 2));
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Close all positions function |
|
|
//+------------------------------------------------------------------+
|
|
void CloseAllPositions()
|
|
{
|
|
ClosePositionModifier closePositionModifier(GetPointer(tradeContext));
|
|
Modify(EnumToString(Action::CLOSE_ALL_POSITIONS), &closePositionModifier);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Close expert positions function |
|
|
//+------------------------------------------------------------------+
|
|
void CloseExpertPositions()
|
|
{
|
|
ClosePositionModifier closePositionModifier(GetPointer(tradeContext), true);
|
|
Modify(EnumToString(Action::CLOSE_EXPERT_POSITIONS), &closePositionModifier);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Defend all positions function |
|
|
//+------------------------------------------------------------------+
|
|
void DefendAllPositions()
|
|
{
|
|
DefendModifier defendModifier(GetPointer(tradeContext));
|
|
Modify(EnumToString(Action::DEFEND_ALL_POSITIONS), &defendModifier);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Defend expert positions function |
|
|
//+------------------------------------------------------------------+
|
|
void DefendExpertPositions()
|
|
{
|
|
DefendModifier defendModifier(GetPointer(tradeContext), true);
|
|
Modify(EnumToString(Action::DEFEND_EXPERT_POSITIONS), &defendModifier);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Modify function |
|
|
//+------------------------------------------------------------------+
|
|
void Modify(const string message, Modifier* modifier)
|
|
{
|
|
Print(message);
|
|
ModifyPositions(modifier);
|
|
PlaySoundFile(SOUND_ENABLED, SOUND_FILE_NAME);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Modify positions function |
|
|
//+------------------------------------------------------------------+
|
|
void ModifyPositions(Modifier* modifier)
|
|
{
|
|
for(int i = PositionsTotal() - 1; i >= 0; i--)
|
|
{
|
|
if(positionInfo.SelectByIndex(i))
|
|
{
|
|
modifier.Modify();
|
|
}
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Reverse all positions function |
|
|
//+------------------------------------------------------------------+
|
|
void ReverseAllPositions()
|
|
{
|
|
ReversePositions(true);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Reverse expert positions function |
|
|
//+------------------------------------------------------------------+
|
|
void ReverseExpertPositions()
|
|
{
|
|
ReversePositions(false);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Reverse positions function |
|
|
//+------------------------------------------------------------------+
|
|
void ReversePositions(const bool allPositions)
|
|
{
|
|
Action action;
|
|
if(allPositions)
|
|
{
|
|
action = Action::REVERSE_ALL_POSITIONS;
|
|
}
|
|
else
|
|
{
|
|
action = Action::REVERSE_EXPERT_POSITIONS;
|
|
}
|
|
Print(EnumToString(action));
|
|
if(positionInfo.SelectByIndex(0))
|
|
{
|
|
switch(positionInfo.PositionType())
|
|
{
|
|
case ENUM_POSITION_TYPE::POSITION_TYPE_BUY:
|
|
action = Action::SELL;
|
|
break;
|
|
case ENUM_POSITION_TYPE::POSITION_TYPE_SELL:
|
|
action = Action::BUY;
|
|
break;
|
|
}
|
|
}
|
|
if(allPositions)
|
|
{
|
|
CloseAllPositions();
|
|
}
|
|
else
|
|
{
|
|
CloseExpertPositions();
|
|
}
|
|
if(action != Action::UNKNOWN)
|
|
{
|
|
PositionOpen(action);
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Sell function |
|
|
//+------------------------------------------------------------------+
|
|
void Sell()
|
|
{
|
|
PositionOpen(Action::SELL);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Sell limit function |
|
|
//+------------------------------------------------------------------+
|
|
void SellLimit()
|
|
{
|
|
OrderOpen(Action::SELL_LIMIT);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Sell protect function |
|
|
//+------------------------------------------------------------------+
|
|
void SellProtect()
|
|
{
|
|
ProtectModifier protectModifier(GetPointer(tradeContext));
|
|
Modify(EnumToString(Action::SELL_PROTECT), &protectModifier);
|
|
Sell();
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Sell pyramid function |
|
|
//+------------------------------------------------------------------+
|
|
void SellPyramid()
|
|
{
|
|
sellPyramid = true;
|
|
PositionOpen(Action::SELL);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Sell stop function |
|
|
//+------------------------------------------------------------------+
|
|
void SellStop()
|
|
{
|
|
OrderOpen(Action::SELL_STOP);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Position open function |
|
|
//+------------------------------------------------------------------+
|
|
void PositionOpen(const int action)
|
|
{
|
|
ENUM_ORDER_TYPE orderType;
|
|
double price;
|
|
double deltaStopLoss;
|
|
double deltaTakeProfit;
|
|
symbolInfo.RefreshRates();
|
|
switch(action)
|
|
{
|
|
case Action::BUY:
|
|
orderType = ENUM_ORDER_TYPE::ORDER_TYPE_BUY;
|
|
price = symbolInfo.Ask();
|
|
buyPyramidPriceOpen = price;
|
|
deltaStopLoss = -STOP_LOSS;
|
|
deltaTakeProfit = TAKE_PROFIT;
|
|
break;
|
|
case Action::SELL:
|
|
orderType = ENUM_ORDER_TYPE::ORDER_TYPE_SELL;
|
|
price = symbolInfo.Bid();
|
|
sellPyramidPriceOpen = price;
|
|
deltaStopLoss = STOP_LOSS;
|
|
deltaTakeProfit = -TAKE_PROFIT;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
Print(EnumToString((Action) action));
|
|
double stopLoss = IsZero(STOP_LOSS) ? 0.0 : symbolInfo.NormalizePrice(price + deltaStopLoss);
|
|
double takeProfit = IsZero(TAKE_PROFIT) ? 0.0 : symbolInfo.NormalizePrice(price + deltaTakeProfit);
|
|
trade.PositionOpen(_Symbol, orderType, CONTRACTS, price, stopLoss, takeProfit);
|
|
PlaySoundFile(SOUND_ENABLED, SOUND_FILE_NAME);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Order open function |
|
|
//+------------------------------------------------------------------+
|
|
void OrderOpen(const int action)
|
|
{
|
|
ENUM_ORDER_TYPE orderType;
|
|
double price;
|
|
double deltaStopLoss;
|
|
double deltaTakeProfit;
|
|
symbolInfo.RefreshRates();
|
|
switch(action)
|
|
{
|
|
case Action::BUY_LIMIT:
|
|
orderType = ENUM_ORDER_TYPE::ORDER_TYPE_BUY_LIMIT;
|
|
price = symbolInfo.Ask() - STOP_LOSS;
|
|
deltaStopLoss = -STOP_LOSS;
|
|
deltaTakeProfit = TAKE_PROFIT;
|
|
break;
|
|
case Action::BUY_STOP:
|
|
orderType = ENUM_ORDER_TYPE::ORDER_TYPE_BUY_STOP;
|
|
price = symbolInfo.Ask() + STOP_LOSS;
|
|
deltaStopLoss = -STOP_LOSS;
|
|
deltaTakeProfit = TAKE_PROFIT;
|
|
break;
|
|
case Action::SELL_LIMIT:
|
|
orderType = ENUM_ORDER_TYPE::ORDER_TYPE_SELL_LIMIT;
|
|
price = symbolInfo.Bid() + STOP_LOSS;
|
|
deltaStopLoss = STOP_LOSS;
|
|
deltaTakeProfit = -TAKE_PROFIT;
|
|
break;
|
|
case Action::SELL_STOP:
|
|
orderType = ENUM_ORDER_TYPE::ORDER_TYPE_SELL_STOP;
|
|
price = symbolInfo.Bid() - STOP_LOSS;
|
|
deltaStopLoss = STOP_LOSS;
|
|
deltaTakeProfit = -TAKE_PROFIT;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
Print(EnumToString((Action) action));
|
|
double stopLoss = IsZero(STOP_LOSS) ? 0.0 : symbolInfo.NormalizePrice(price + deltaStopLoss);
|
|
double takeProfit = IsZero(TAKE_PROFIT) ? 0.0 : symbolInfo.NormalizePrice(price + deltaTakeProfit);
|
|
trade.OrderOpen(_Symbol, orderType, CONTRACTS, price, price, stopLoss, takeProfit);
|
|
PlaySoundFile(SOUND_ENABLED, SOUND_FILE_NAME);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert deinitialization function |
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason)
|
|
{
|
|
actions.Clear();
|
|
EventKillTimer();
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert initialization function |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
if(!symbolInfo.Name(_Symbol))
|
|
{
|
|
PlaySoundFile(SOUND_ENABLED, SOUND_FILE_NAME);
|
|
return(INIT_FAILED);
|
|
}
|
|
InitActions();
|
|
if(!IsKeyMappingCorrect())
|
|
{
|
|
PlaySoundFile(SOUND_ENABLED, SOUND_FILE_NAME);
|
|
return(INIT_PARAMETERS_INCORRECT);
|
|
}
|
|
EventSetTimer(1);
|
|
trade.SetAsyncMode(ASYNC_MODE_ENABLED);
|
|
trade.SetExpertMagicNumber(MAGIC);
|
|
tradeContext.Init(positionInfo, symbolInfo, trade);
|
|
InitLastProfits();
|
|
InitPositions();
|
|
actionsUsage = actions.Usage();
|
|
Print(actionsUsage);
|
|
return(INIT_SUCCEEDED);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Actions initialization function |
|
|
//+------------------------------------------------------------------+
|
|
void InitActions()
|
|
{
|
|
actions.AddAction(buyActionKey, Action::BUY);
|
|
actions.AddAction(buyLimitActionKey, Action::BUY_LIMIT);
|
|
actions.AddAction(buyProtectActionKey, Action::BUY_PROTECT);
|
|
actions.AddAction(buyPyramidActionKey, Action::BUY_PYRAMID);
|
|
actions.AddAction(buyStopActionKey, Action::BUY_STOP);
|
|
actions.AddAction(closeAllPositionsActionKey, Action::CLOSE_ALL_POSITIONS);
|
|
actions.AddAction(closeExpertPositionsActionKey, Action::CLOSE_EXPERT_POSITIONS);
|
|
actions.AddAction(defendAllPositionsActionKey, Action::DEFEND_ALL_POSITIONS);
|
|
actions.AddAction(defendExpertPositionsActionKey, Action::DEFEND_EXPERT_POSITIONS);
|
|
actions.AddAction(exitScalperActionKey, Action::EXIT_SCALPER);
|
|
actions.AddAction(lockActionKey, Action::LOCK);
|
|
actions.AddAction(reverseAllPositionsActionKey, Action::REVERSE_ALL_POSITIONS);
|
|
actions.AddAction(reverseExpertPositionsActionKey, Action::REVERSE_EXPERT_POSITIONS);
|
|
actions.AddAction(sellActionKey, Action::SELL);
|
|
actions.AddAction(sellLimitActionKey, Action::SELL_LIMIT);
|
|
actions.AddAction(sellProtectActionKey, Action::SELL_PROTECT);
|
|
actions.AddAction(sellPyramidActionKey, Action::SELL_PYRAMID);
|
|
actions.AddAction(sellStopActionKey, Action::SELL_STOP);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Last profits initialization function |
|
|
//+------------------------------------------------------------------+
|
|
void InitLastProfits()
|
|
{
|
|
ArrayFree(lastProfits);
|
|
datetime now = TimeCurrent();
|
|
datetime yesterday = now - 86400; // PERIOD_D1 * 60
|
|
HistorySelect(yesterday, now);
|
|
int lastProfitIndex = 0;
|
|
LastProfit historyLastProfits[];
|
|
for(int i = HistoryDealsTotal() - 1; i >= 0; i--)
|
|
{
|
|
if(lastProfitIndex >= LAST_PROFITS_SIZE)
|
|
{
|
|
break;
|
|
}
|
|
ulong dealTicket = HistoryDealGetTicket(i);
|
|
double dealProfit = HistoryDealGetDouble(dealTicket, DEAL_PROFIT);
|
|
if(IsZero(dealProfit))
|
|
{
|
|
continue;
|
|
}
|
|
long dealReason = HistoryDealGetInteger(dealTicket, DEAL_REASON);
|
|
if(IsStandardDealReason((int) dealReason))
|
|
{
|
|
LastProfit lastProfitStruct;
|
|
lastProfitStruct.message = GetMessage(dealTicket);
|
|
lastProfitStruct.profit = dealProfit;
|
|
lastProfitStruct.suffix = GetSuffix(dealReason);
|
|
ArrayResize(historyLastProfits, historyLastProfits.Size() + 1);
|
|
historyLastProfits[lastProfitIndex] = lastProfitStruct;
|
|
lastProfitIndex++;
|
|
}
|
|
}
|
|
for(int i = (int) historyLastProfits.Size() - 1; i >= 0; i--)
|
|
{
|
|
AddLastProfit(historyLastProfits[i]);
|
|
}
|
|
CalculateTotalLastProfit();
|
|
SetLastProfit();
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Get message function |
|
|
//+------------------------------------------------------------------+
|
|
string GetMessage(const ulong dealTicket)
|
|
{
|
|
switch((int) HistoryDealGetInteger(dealTicket, DEAL_TYPE))
|
|
{
|
|
case ENUM_DEAL_TYPE::DEAL_TYPE_BUY:
|
|
return MESSAGE_SELL;
|
|
case ENUM_DEAL_TYPE::DEAL_TYPE_SELL:
|
|
return MESSAGE_BUY;
|
|
}
|
|
return "";
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Get suffix function |
|
|
//+------------------------------------------------------------------+
|
|
string GetSuffix(const long dealReason)
|
|
{
|
|
if(dealReason == DEAL_REASON_SL)
|
|
{
|
|
return "(stop loss) ";
|
|
}
|
|
if(dealReason == DEAL_REASON_TP)
|
|
{
|
|
return "(take profit) ";
|
|
}
|
|
return "";
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Positions initialization function |
|
|
//+------------------------------------------------------------------+
|
|
void InitPositions()
|
|
{
|
|
ulong allPositionsTickets[];
|
|
int positionsTotal = PositionsTotal();
|
|
Print("positionsTotal: ", positionsTotal);
|
|
ArrayFree(allPositionsTickets);
|
|
ArrayResize(allPositionsTickets, positionsTotal);
|
|
for(int i = 0; i < positionsTotal; i++)
|
|
{
|
|
if(positionInfo.SelectByIndex(i))
|
|
{
|
|
allPositionsTickets[i] = positionInfo.Ticket();
|
|
}
|
|
}
|
|
ArrayPrint(allPositionsTickets);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Tick function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTick()
|
|
{
|
|
if(!(buyPyramid || sellPyramid))
|
|
{
|
|
return;
|
|
}
|
|
symbolInfo.RefreshRates();
|
|
if(buyPyramid && (symbolInfo.Ask() > buyPyramidPriceOpen + STOP_LOSS))
|
|
{
|
|
DefendAllPositions();
|
|
PositionOpen(Action::BUY);
|
|
}
|
|
if(sellPyramid && (symbolInfo.Bid() < sellPyramidPriceOpen - STOP_LOSS))
|
|
{
|
|
DefendAllPositions();
|
|
PositionOpen(Action::SELL);
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Timer function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTimer()
|
|
{
|
|
string comment = StringFormat(INDENT_FORMAT, TimeToString(TimeLocal(), TIME_MINUTES | TIME_SECONDS));
|
|
comment += lastProfit;
|
|
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);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| ToDo |
|
|
//| - error processing |
|
|
//| - objects |
|
|
//+------------------------------------------------------------------+
|