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

266 lines
10 KiB
MQL5

//+------------------------------------------------------------------+
//| CalculateBreakeven.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 "BreakEvenResult.mqh"
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class CalculateBreakeven
{
private:
int Total_Buy_Trades;
double Total_Buy_Size;
double Total_Buy_Price;
double Buy_Profit;
//---
int Total_Sell_Trades;
double Total_Sell_Size;
double Total_Sell_Price;
double Sell_Profit;
int PipAdjust,NrOfDigits;
double point;
public:
CalculateBreakeven();
~CalculateBreakeven();
BreakEvenHedgeTicketsResult GetHedge(double lotsize,long magicnumber);
BreakEvenResult GetBreakEven(const BreakEvenInput &breakEvenInput);
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CalculateBreakeven::CalculateBreakeven()
{
if(NrOfDigits==5 || NrOfDigits==3)
PipAdjust=10;
else
if(NrOfDigits==4 || NrOfDigits==2)
PipAdjust=1;
//---
point=Point()*PipAdjust;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CalculateBreakeven::~CalculateBreakeven()
{
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
BreakEvenHedgeTicketsResult CalculateBreakeven::GetHedge(double lotsize,long magicnumber)
{
CPositionInfo m_position;
BreakEvenHedgeTicketsResult result;
int total=PositionsTotal();
if(magicnumber==0)
return result;
//---
datetime oldestbuy=TimeCurrent();
datetime oldestsell=TimeCurrent();
double oldestbuylotsize=0;
double oldestsellLotsize=0;
ulong oldestBuyTicket=0;
ulong oldestSellTicket=0;
double lotSizeFilledBuy=0;
double lotSizeFilledSell=0;
lotsize=NormalizeDouble(lotsize,2);
for(int i=0;i<total;i++)
{
int ord=m_position.SelectByIndex(i);
if(m_position.PositionType()==POSITION_TYPE_BUY && m_position.Symbol()==Symbol() && magicnumber!=m_position.Magic())
{
if(lotSizeFilledBuy<lotsize)
{
if(m_position.Volume()<=(lotsize-lotSizeFilledBuy))
{
result.lotsizes.Add(m_position.Volume());
result.ticketnumbers.Add(m_position.Ticket());
result.Buy.Add(1);
lotSizeFilledBuy=NormalizeDouble(lotSizeFilledBuy+m_position.Volume(),2);
}
else if(m_position.Volume()>(lotsize-lotSizeFilledBuy) && ((lotsize-lotSizeFilledBuy)>0))
{
result.lotsizes.Add(lotsize-lotSizeFilledBuy);
result.ticketnumbers.Add(m_position.Ticket());
result.Buy.Add(1);
lotSizeFilledBuy=lotsize;
}
}
}
if(m_position.PositionType()==POSITION_TYPE_SELL && m_position.Symbol()==Symbol() && magicnumber!=m_position.Magic())
{
if(lotSizeFilledSell<lotsize)
{
if(m_position.Volume()<=lotsize-lotSizeFilledSell)
{
result.lotsizes.Add(m_position.Volume());
result.ticketnumbers.Add(m_position.Ticket());
result.Buy.Add(0);
lotSizeFilledSell=NormalizeDouble(lotSizeFilledSell+m_position.Volume(),2);
}
else if(m_position.Volume()>(lotsize-lotSizeFilledSell) && ((lotsize-lotSizeFilledSell)>0))
{
result.lotsizes.Add(lotsize-lotSizeFilledSell);
result.ticketnumbers.Add(m_position.Ticket());
result.Buy.Add(0);
lotSizeFilledSell=lotsize;
}
}
}
}
return result;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
BreakEvenResult CalculateBreakeven::GetBreakEven(const BreakEvenInput &breakEvenInput)
{
Total_Buy_Trades=0;
Total_Buy_Size=0;
Total_Buy_Price=0;
Buy_Profit=0;
//---
Total_Sell_Trades=0;
Total_Sell_Size=0;
Total_Sell_Price=0;
Sell_Profit=0;
BreakEvenResult result;
BreakEvenHedgeTicketsResult hedges=GetHedge(breakEvenInput.HedgeToBreakDownLots,breakEvenInput.MagicNumber);
CPositionInfo m_position;
double Pip_Value=SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE)*PipAdjust;
double Pip_Size=SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE)*PipAdjust;
//---
int total=PositionsTotal();
//---
for(int i=0;i<total;i++)
{
int ord=m_position.SelectByIndex(i);
{
if(m_position.PositionType()==POSITION_TYPE_BUY && m_position.Symbol()==Symbol() && breakEvenInput.Buys==true &&((breakEvenInput.MagicNumber==0)||(m_position.Magic()==breakEvenInput.MagicNumber)))
{
Total_Buy_Trades++;
Total_Buy_Price+=m_position.PriceOpen()*m_position.Volume();
Total_Buy_Size += m_position.Volume();
Buy_Profit+=m_position.Profit()+m_position.Swap()+m_position.Commission();
result.TicketsToClose.Add(m_position.Ticket());
result.TicketsLotSizeToClose.Add(m_position.Volume());
}
if(m_position.PositionType()==POSITION_TYPE_BUY && m_position.Symbol()==Symbol() && breakEvenInput.Buys==true &&((breakEvenInput.MagicNumber!=0)&&(m_position.Magic()!=breakEvenInput.MagicNumber)))
{
long temptic=m_position.Ticket();
int index=-1;
for(int y=0;y<hedges.ticketnumbers.Total();y++)
{
if(hedges.ticketnumbers.At(y)==temptic)
index=y;
}
if(index>-1)
{
double portionvolume=hedges.lotsizes.At(index);
Total_Buy_Trades++;
Total_Buy_Price+=m_position.PriceOpen()*portionvolume;
Total_Buy_Size += portionvolume;
Buy_Profit+=(m_position.Profit()*portionvolume)/m_position.Volume()+(m_position.Swap()*portionvolume)/m_position.Volume()+(m_position.Commission()*portionvolume)/m_position.Volume();
result.TicketsToClose.Add(m_position.Ticket());
result.TicketsLotSizeToClose.Add(portionvolume);
}
}
if(m_position.PositionType()==POSITION_TYPE_SELL && m_position.Symbol()==Symbol() && breakEvenInput.Sells==true && ((breakEvenInput.MagicNumber==0)||(m_position.Magic()==breakEvenInput.MagicNumber)))
{
Total_Sell_Trades++;
Total_Sell_Size+=m_position.Volume();
Total_Sell_Price+=m_position.PriceOpen()*m_position.Volume();
Sell_Profit+=m_position.Profit()+m_position.Swap()+m_position.Commission();
result.TicketsToClose.Add(m_position.Ticket());
result.TicketsLotSizeToClose.Add(m_position.Volume());
}
if(m_position.PositionType()==POSITION_TYPE_SELL && m_position.Symbol()==Symbol() && breakEvenInput.Sells==true && ((breakEvenInput.MagicNumber!=0)&&(m_position.Magic()!=breakEvenInput.MagicNumber)))
{
long temptic=m_position.Ticket();
int index=-1;
for(int y=0;y<hedges.ticketnumbers.Total();y++)
{
if(hedges.ticketnumbers.At(y)==temptic)
index=y;
}
if(index>-1)
{
double portionvolume=hedges.lotsizes.At(index);
Total_Sell_Trades++;
Total_Sell_Size+=portionvolume;
Total_Sell_Price+=m_position.PriceOpen()*portionvolume;
Sell_Profit+=(m_position.Profit()*portionvolume)/m_position.Volume()+(m_position.Swap()*portionvolume)/m_position.Volume()+(m_position.Commission()*portionvolume)/m_position.Volume();
result.TicketsToClose.Add(m_position.Ticket());
result.TicketsLotSizeToClose.Add(portionvolume);
}
}
}
}
if(Total_Buy_Price>0)
{
Total_Buy_Price/=Total_Buy_Size;
}
if(Total_Sell_Price>0)
{
Total_Sell_Price/=Total_Sell_Size;
}
result.Net_Trades=Total_Buy_Trades+Total_Sell_Trades;
result.Net_Lots=Total_Buy_Size-Total_Sell_Size;
result.Net_Result=Buy_Profit+Sell_Profit;
if(result.Net_Trades>0 && result.Net_Lots!=0)
{
result.distance=(((result.Net_Result-breakEvenInput.ProfitInMoney)/(MathAbs(result.Net_Lots*SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE))))*SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE));
if(result.Net_Lots>0)
{
result.Average_Price= SymbolInfoDouble(_Symbol, SYMBOL_BID)- result.distance;
}
if(result.Net_Lots<0)
{
result.Average_Price= SymbolInfoDouble(_Symbol, SYMBOL_ASK)+ result.distance;
}
}
if(result.Net_Trades>0 && result.Net_Lots==0)
{
result.distance=(result.Net_Result/((SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE)))*SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE));
result.Average_Price=SymbolInfoDouble(_Symbol, SYMBOL_BID)-result.distance;
}
return(result);
}
//+------------------------------------------------------------------+