SonnyPanel/Includes/OrderManager.mqh
super.admin cfd1ba1ff5 convert
2025-05-30 16:25:20 +02:00

418 lines
15 KiB
MQL5

//+------------------------------------------------------------------+
//| PlaceOrders.mqh |
//| Copyright 2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
#include "..\\Includes\\CalculateBreakeven.mqh"
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class OrderManager
{
private:
public:
int recoveryOrdersSell;
int recoveryOrdersBuy;
CPositionInfo m_position;
CTrade m_trade;
OrderManager();
~OrderManager();
void CloseTrades(long MagicNumber,bool buy,bool sell,double profit=0,double parttoclose=0);
void TrailTrades(long MagicNumber,bool buy,bool sell,double profit,double parttoclose, double iTrailingStart, double iTrailStep,double iTrailingStop);
int HedgePositions(long MagicNumber);
void FirstOrder(long Mymagic,double Volume);
bool PlaceOrder(ENUM_POSITION_TYPE TypeOrder, double Volume, int magic, string Comment);
double RelativeProfitOnMagic(long MyMagic,double lots,double min,double lotstobreakdown,datetime hedge,bool proces,bool forcerecover);
double RelativeProfitOnMagic2(long MyMagic,double lots,double min,double lotstobreakdown,datetime hedge,bool proces,bool forcerecover);
double TrallB ;
double LastOrderProfit();
long GetDirectionOfTheLastProfitTrade(int mtype, string symbol, int magicx);
void CloseAll();
int PositionTotalOnThis();
bool ToMuchMagic();
int GetHighestMagic();
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
OrderManager::OrderManager()
{
m_trade.SetTypeFillingBySymbol(m_position.Symbol());
TrallB = 0;
recoveryOrdersSell=0;
recoveryOrdersBuy=0;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
OrderManager::~OrderManager()
{
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void OrderManager::FirstOrder(long Mymagic,double Volume)
{
MqlRates rates[];
CopyRates(Symbol(),PERIOD_M15,0,2,rates);
MqlTick tick;
if(!SymbolInfoTick(Symbol(),tick))
Print("SymbolInfoTick() failed, error = ",GetLastError());
if(GetDirectionOfTheLastProfitTrade(-99, _Symbol, -1)== DEAL_TYPE_BUY)
{
if(!PlaceOrder(POSITION_TYPE_SELL,Volume,Mymagic,NULL))
printf("error");
}
else
{
if(!PlaceOrder(POSITION_TYPE_BUY,Volume,Mymagic,NULL))
printf("error");
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
long OrderManager::GetDirectionOfTheLastProfitTrade(int mtype, string symbol, int magicx)
{
ulong ticket=0;
int cta=0;
HistorySelect(0,TimeCurrent());
for(int i=HistoryOrdersTotal(); i>=0; i--)
{
if((ticket=HistoryDealGetTicket(i))>0)
{
if(HistoryDealGetInteger(ticket,DEAL_ENTRY) == DEAL_ENTRY_OUT)
{
string s= HistoryDealGetString(ticket,DEAL_SYMBOL);
if(s==symbol || symbol=="ALL")
{
long type =HistoryDealGetInteger(ticket,DEAL_TYPE);
if(type==mtype || mtype==-99)
{
long m =HistoryDealGetInteger(ticket, DEAL_MAGIC);
if(m==magicx || magicx==-1)
{
double profit=HistoryDealGetDouble(ticket, DEAL_PROFIT);
if(profit>0)
return type;
}
}
}
}
}
}
return 0;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double OrderManager::LastOrderProfit()
{
int totalPositions = PositionsTotal();
double lastPositionProfit = 0.0;
for (int i = totalPositions - 1; i >= 0; i--) {
ulong ticket = PositionGetTicket(i);
if (PositionSelectByTicket(ticket)) {
if (PositionGetString(POSITION_SYMBOL) == _Symbol) {
lastPositionProfit = PositionGetDouble(POSITION_PROFIT);
break;
}
}
}
return lastPositionProfit;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double OrderManager::RelativeProfitOnMagic(long MyMagic,double lots,double min,double lotstobreakdown,datetime hedge,bool proces,bool forcerecover)
{
MqlDateTime rightNow;
TimeCurrent(rightNow);
CalculateBreakeven breakEven;
m_trade.SetMarginMode();
BreakEvenInput breakEvenInput;
breakEvenInput.Buys=true;
breakEvenInput.Sells=true;
breakEvenInput.MagicNumber=MyMagic;
breakEvenInput.ProfitInMoney=0;
breakEvenInput.HedgeToBreakDownLots=lotstobreakdown;
BreakEvenResult breakevenResult=breakEven.GetBreakEven(breakEvenInput);
//
if((NormalizeDouble(breakevenResult.Net_Lots,2)==0) && proces && breakevenResult.Net_Trades>0 )
{
FirstOrder(MyMagic, lots);
FirstOrder(MyMagic, lots);
FirstOrder(MyMagic, lots);
FirstOrder(MyMagic, lots);
recoveryOrdersBuy=0;
recoveryOrdersSell=0;
}
//&&(hedge+=0* PeriodSeconds(PERIOD_H1))<TimeCurrent()
double relativ= (breakevenResult.Net_Result*MathAbs(lots/(breakevenResult.Net_Lots==0?lots:breakevenResult.Net_Lots)));
if((LastOrderProfit()<min) && breakevenResult.Net_Lots>0 )
{
if(recoveryOrdersBuy<(MyMagic>1?2:3))
{
PlaceOrder(POSITION_TYPE_BUY,lots,MyMagic,MyMagic);
recoveryOrdersBuy=recoveryOrdersBuy+1;
recoveryOrdersSell=0;
}
}
if((LastOrderProfit()<min) && breakevenResult.Net_Lots<0 )
{
if(recoveryOrdersSell<(MyMagic>1?2:3))
{
PlaceOrder(POSITION_TYPE_SELL,lots,MyMagic,MyMagic);
recoveryOrdersBuy=0;
recoveryOrdersSell=recoveryOrdersSell+1;
}
}
return breakevenResult.Net_Result;
}
double OrderManager::RelativeProfitOnMagic2(long MyMagic,double lots,double min,double lotstobreakdown,datetime hedge,bool proces,bool forcerecover)
{
MqlDateTime rightNow;
TimeCurrent(rightNow);
CalculateBreakeven breakEven;
m_trade.SetMarginMode();
BreakEvenInput breakEvenInput;
breakEvenInput.Buys=true;
breakEvenInput.Sells=true;
breakEvenInput.MagicNumber=MyMagic;
breakEvenInput.ProfitInMoney=0;
breakEvenInput.HedgeToBreakDownLots=lotstobreakdown;
BreakEvenResult breakevenResult=breakEven.GetBreakEven(breakEvenInput);
//
// if(((NormalizeDouble(breakevenResult.Net_Lots,2)==0)&&(hedge+=0* PeriodSeconds(PERIOD_H1))<TimeCurrent() && proces && breakevenResult.Net_Trades>0 && rightNow.hour>10)||forcerecover)
// FirstOrder(MyMagic, lots);
/*
double relativ= (breakevenResult.Net_Result*MathAbs(lots/(breakevenResult.Net_Lots==0?lots:breakevenResult.Net_Lots)));
if((LastOrderProfit()<min) && breakevenResult.Net_Lots>0 && proces){
if (recoveryOrdersBuy<4){
PlaceOrder(POSITION_TYPE_BUY,lots,MyMagic,NULL);
recoveryOrdersBuy=recoveryOrdersBuy+1;
recoveryOrdersSell=0;}
}
if((LastOrderProfit()<min) && breakevenResult.Net_Lots<0 && proces){
if (recoveryOrdersSell<4){
PlaceOrder(POSITION_TYPE_SELL,lots,MyMagic,NULL);
recoveryOrdersBuy=0;
recoveryOrdersSell=recoveryOrdersSell+1;
}}
*/
return breakevenResult.Net_Result;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool OrderManager::PlaceOrder(ENUM_POSITION_TYPE TypeOrder, double Volume, int magic, string Comment)
{
m_trade.SetExpertMagicNumber(magic);
if(TypeOrder == POSITION_TYPE_BUY)
{
if(!m_trade.Buy(Volume,Symbol(),0,0,0,Comment))
return(false);
}
if(TypeOrder == POSITION_TYPE_SELL)
{
if(!m_trade.Sell(Volume,Symbol(),0,0,0,Comment))
return(false);
}
return(true);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void OrderManager::CloseAll()
{
for(int i=PositionsTotal()-1; i>=0; i--) // returns the number of current positions
if(m_position.SelectByIndex(i))
{
m_trade.PositionClose(m_position.Ticket());
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int OrderManager::PositionTotalOnThis()
{
int total=0;
for(int i=PositionsTotal()-1; i>=0; i--) // returns the number of current positions
if(m_position.SelectByIndex(i))
{
if(m_position.Symbol()==_Symbol)
total=total+1;
}
return total;
}
bool OrderManager::ToMuchMagic()
{
MqlDateTime SDateTime;
TimeToStruct(TimeCurrent(),SDateTime);
SDateTime.hour=0;
SDateTime.min=0;
SDateTime.sec=0;
datetime from_date=StructToTime(SDateTime); // From date
SDateTime.hour=10;
SDateTime.min=59;
SDateTime.sec=59;
datetime to_date=StructToTime(SDateTime); // To date
to_date-=60*60*24;
return true;
}
int OrderManager::GetHighestMagic()
{
int magic=1;
for(int i=PositionsTotal()-1; i>=0; i--) // returns the number of current positions
if(m_position.SelectByIndex(i))
{
if(m_position.Symbol()==_Symbol)
if (m_position.Magic()>magic)
magic=m_position.Magic();
}
return magic;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void OrderManager::CloseTrades(long MagicNumber,bool buy,bool sell,double profit=0,double parttoclose=0)
{
CalculateBreakeven breakEven;
m_trade.SetMarginMode();
BreakEvenInput breakEvenInput;
breakEvenInput.Buys=true;
breakEvenInput.Sells=true;
breakEvenInput.MagicNumber=MagicNumber;
breakEvenInput.ProfitInMoney=profit;
breakEvenInput.HedgeToBreakDownLots=parttoclose;
BreakEvenResult breakevenResult=breakEven.GetBreakEven(breakEvenInput);
if((breakevenResult.Net_Lots>0 && SymbolInfoDouble(_Symbol, SYMBOL_BID)>=breakevenResult.Average_Price) || (breakevenResult.Net_Lots<0 && SymbolInfoDouble(_Symbol, SYMBOL_ASK)<=breakevenResult.Average_Price)|| profit==0 || MagicNumber==0)
for(int i=breakevenResult.TicketsToClose.Total()-1; i>=0; i--) // returns the number of current positions
if(m_position.SelectByTicket(breakevenResult.TicketsToClose.At(i))) // selects the position by index for further access to its properties
{
if(breakevenResult.TicketsLotSizeToClose.At(i)==0)
printf("error zero volume");
m_trade.PositionClosePartial(m_position.Ticket(),breakevenResult.TicketsLotSizeToClose.At(i));
recoveryOrdersSell=0;
recoveryOrdersBuy=0;
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void OrderManager::TrailTrades(long MagicNumber,bool buy,bool sell,double profit,double parttoclose, double iTrailingStart, double iTrailStep,double iTrailingStop)
{
CalculateBreakeven breakEven;
m_trade.SetMarginMode();
BreakEvenInput breakEvenInput;
breakEvenInput.Buys=true;
breakEvenInput.Sells=true;
breakEvenInput.MagicNumber=MagicNumber;
breakEvenInput.ProfitInMoney=profit;
breakEvenInput.HedgeToBreakDownLots=parttoclose;
BreakEvenResult breakevenResult=breakEven.GetBreakEven(breakEvenInput);
double p = breakevenResult.Net_Result;
if(breakevenResult.TicketsToClose.Total()==0)
TrallB=0;
double SL=breakevenResult.Net_Result-iTrailingStop;
if(breakevenResult.Net_Result>=iTrailingStart && (TrallB==0 || TrallB+iTrailStep<SL))
TrallB=SL;
if((breakevenResult.Net_Result<=TrallB) && (TrallB>0))
for(int i=breakevenResult.TicketsToClose.Total()-1; i>=0; i--)
if(m_position.SelectByTicket(breakevenResult.TicketsToClose.At(i)))
{
{
m_trade.PositionClosePartial(m_position.Ticket(),breakevenResult.TicketsLotSizeToClose.At(i));
recoveryOrdersSell=0;
recoveryOrdersBuy=0;
}
TrallB=0;
}
}
//+------------------------------------------------------------------+
int OrderManager::HedgePositions(long MagicNumber)
{
CalculateBreakeven breakEven;
m_trade.SetMarginMode();
BreakEvenInput breakEvenInput;
breakEvenInput.Buys=true;
breakEvenInput.Sells=true;
BreakEvenResult breakevenResult=breakEven.GetBreakEven(breakEvenInput);
if(breakevenResult.Net_Lots<0)
{
PlaceOrder(POSITION_TYPE_BUY,NormalizeDouble(MathAbs(breakevenResult.Net_Lots),2),MagicNumber,"HEDGE");
return 1;
}
if(breakevenResult.Net_Lots>0)
{
PlaceOrder(POSITION_TYPE_SELL,NormalizeDouble(breakevenResult.Net_Lots,2),MagicNumber,"HEDGE");
return 0;
}
return 0;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+