window_rep/include/StandartFunctions.mqh

621 lines
49 KiB
MQL5
Raw Permalink Normal View History

2025-10-09 20:54:49 +03:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| StandartFunctions.mqh |
//| AHMAD KAZBAR |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "AHMAD KAZBAR"
#property version "1.00"
#include <Trade/Trade.mqh>
#include <Trade/PositionInfo.mqh>
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class CBar : public CObject
{
public:
double c;
double o;
double h;
double l;
datetime t;
int i;
bool p ;
string type;
CBar(double _c,double _o,double _h,double _l,datetime _t,int _i,string _type,bool peak)
{
c = _c;
o = _o;
h = _h;
l = _l;
t= _t;
i = _i;
p = peak;
type = _type;
}
bool Equals(double val,double val2) { return val == val2; }
};
struct STradeSum
{
int count;
double profit;
double trailPrice;
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class StandartFunctions
{
private:
string m_symbol;
ENUM_TIMEFRAMES m_timeFrame;
int m_digits;
CTrade m_trade;
long m_magic;
datetime previous_time;
bool m_print_log;
public:
StandartFunctions(string symbol,ENUM_TIMEFRAMES timeFrame,long exMagic,bool p_log = false)
{
m_symbol = symbol;
m_timeFrame = timeFrame;
m_magic = exMagic;
m_digits = (int)SymbolInfoInteger(m_symbol,SYMBOL_DIGITS);
m_trade.SetExpertMagicNumber(exMagic);
IsNewBar();
m_print_log = p_log;
}
StandartFunctions();
~StandartFunctions();
bool IsNewBar();
bool IsNewBarDay();
double High(int shift);
double Close(int shift);
double Low(int shift);
double Open(int shift);
datetime Time(int shift);
double Bid();
double Ask();
double PipeToDouble(double pips);
double CalculateLotByBalance();
double tr(int shifit);
double CalculatePipsFromDollars(double dollarAmount,double lotSize);
double CalcLots(double slPoints);
double Size(int shift);
ulong BuyLimit(double lot,double entry,double stop,double tp,string comment,datetime expirt);
ulong SellLimit(double lot,double entry,double stop,double tp,string comment,datetime expirt);
ulong BuyStop(double lot,double entry,double stop,double tp,string comment,datetime expirt);
ulong SellStop(double lot,double entry,double stop,double tp,string comment,datetime expirt);
ulong OpenOrder(ENUM_ORDER_TYPE OrderType,double lot,double entry,double stop,double tp,string comment);
void UpdatePosition(double trailingPips,double target);
bool UpdatePosition(const ulong ticket,const double sl,const double tp);
void GetTradeSum(STradeSum &sum,ENUM_POSITION_TYPE type);
void DrawArrow(string name, datetime arrowTime, double arrowPrice, string direction = "up", color clr = clrLime, int size = 2);
bool IsPivotHigh(int index,int Left,int Right,const MqlRates &m_rates[]);
bool IsPivotLow(int index,int Left,int Right,const MqlRates &m_rates[]);
bool CheckTradeAllowed();
ENUM_TIMEFRAMES GetTimeFrame(){return m_timeFrame;}
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
StandartFunctions::StandartFunctions()
{
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
StandartFunctions::~StandartFunctions()
{
}
//+------------------------------------------------------------------+
double StandartFunctions::High(int shift) {return iHigh(m_symbol,m_timeFrame,shift);}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double StandartFunctions::Low(int shift) {return iLow(m_symbol,m_timeFrame,shift);}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double StandartFunctions::Close(int shift) {return iClose(m_symbol,m_timeFrame,shift);}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double StandartFunctions::Open(int shift) {return iOpen(m_symbol,m_timeFrame,shift);}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
datetime StandartFunctions::Time(int shift) {return iTime(m_symbol,m_timeFrame,shift);}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double StandartFunctions::Ask(void) { return NormalizeDouble(SymbolInfoDouble(m_symbol,SYMBOL_ASK),m_digits);}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double StandartFunctions::Bid(void) { return NormalizeDouble(SymbolInfoDouble(m_symbol,SYMBOL_ASK),m_digits);}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void StandartFunctions::GetTradeSum(STradeSum &sum,ENUM_POSITION_TYPE type)
{
sum.count = 0;
sum.profit = 0.0;
sum.trailPrice = 0.0;
int count = PositionsTotal();
if(count <=0)
return;
for(int i = OrdersTotal()-1; i >= 0; i--)
{
COrderInfo order;
if(order.SelectByIndex(i))
{
if(order.Magic() != m_magic)
continue;
if(order.Symbol() != m_symbol)
continue;
///Print(__FUNCTION__," > Found pending order with ticket #",order.Ticket(),"...");
if(order.OrderType() == ORDER_TYPE_BUY_LIMIT)
sum.count++;
if(order.OrderType() == ORDER_TYPE_SELL_LIMIT)
sum.count++;
}
}
for(int i = count-1; i>=0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket>0)
{
if(PositionGetInteger(POSITION_TYPE) == type)
{
sum.count++;
sum.profit += PositionGetDouble(POSITION_PROFIT)+PositionGetDouble(POSITION_SWAP);
double entry = PositionGetDouble(POSITION_PRICE_OPEN);
double profit = PositionGetDouble(POSITION_PROFIT);
if(type==POSITION_TYPE_BUY)
{
if(sum.trailPrice==0 || PositionGetDouble(POSITION_PRICE_OPEN)<sum.trailPrice)
{
sum.trailPrice = PositionGetDouble(POSITION_PRICE_OPEN);
}
}
else
if(type==POSITION_TYPE_SELL)
{
if(sum.trailPrice==0 || PositionGetDouble(POSITION_PRICE_OPEN)>sum.trailPrice)
{
sum.trailPrice = PositionGetDouble(POSITION_PRICE_OPEN);
}
}
}
}
}
return;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool StandartFunctions::IsNewBar(void)
{
datetime current_time = iTime(m_symbol,m_timeFrame,0);
if(previous_time != current_time)
{
previous_time = current_time;
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool StandartFunctions::IsNewBarDay(void)
{
static datetime prevTime = 0;
datetime currentTime = iTime(m_symbol,PERIOD_D1,0);
if(prevTime == currentTime)
return false;
prevTime = currentTime;
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double StandartFunctions::tr(int shift)
{
double t1 = High(shift) - Low(shift) ;
double t2 = MathAbs(High(shift) - Close(shift+1));
double t3 = MathAbs(Low(shift) - Close(shift+1));
return MathMax(MathMax(t1, t2), t3);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double StandartFunctions::Size(int shift)
{
double totalSize = High(shift) - Low(shift);
double totalSize2 = High(shift+1) - Low(shift+1);
return totalSize/totalSize2;
}
//+------------------------------------------------------------------+
double StandartFunctions::PipeToDouble(double pips)
{
return NormalizeDouble(PointsToDouble(m_symbol,pips),m_digits);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
ulong StandartFunctions::OpenOrder(ENUM_ORDER_TYPE OrderType,double lot,double entry,double stoploos,double tp,string comment)
{
ulong result =-1;
if(CanOpenOrder(m_symbol,OrderType,lot,entry))
{
if(!m_trade.PositionOpen(m_symbol,OrderType,lot,entry,stoploos,tp,comment))
return -1;
else
return m_trade.ResultOrder();
}
else
{
return -1;
}
return -1;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
ulong StandartFunctions::BuyLimit(double lot,double entry,double stoploos,double tp,string comment,datetime expirt)
{
if(!m_trade.BuyLimit(lot,entry,m_symbol,stoploos,tp,ORDER_TIME_GTC,expirt,comment))
return -1;
ulong result = m_trade.ResultOrder();
return result;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
ulong StandartFunctions::BuyStop(double lot,double entry,double stoploos,double tp,string comment,datetime expirt)
{
if(!m_trade.BuyStop(lot,entry,m_symbol,stoploos,tp,ORDER_TIME_GTC,expirt,comment))
return -1;
return m_trade.ResultDeal();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
ulong StandartFunctions::SellLimit(double lot,double entry,double stoploos,double tp,string comment,datetime expirt)
{
if(!m_trade.SellLimit(lot,entry,m_symbol,stoploos,tp,ORDER_TIME_GTC,expirt,comment))
return -1;
ulong result = m_trade.ResultOrder();
return result;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
ulong StandartFunctions::SellStop(double lot,double entry,double stoploos,double tp,string comment,datetime expirt)
{
if(!m_trade.SellStop(lot,entry,m_symbol,stoploos,tp,ORDER_TIME_GTC,expirt,comment))
return -1;
return m_trade.ResultDeal();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool StandartFunctions::UpdatePosition(const ulong ticket,const double sl,const double tp)
{
return m_trade.PositionModify(ticket,sl,tp);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void StandartFunctions::DrawArrow(string name, datetime arrowTime, double arrowPrice, string dir = "up", color clr = clrLime, int size = 2)
{
string objName = name + "_" + dir + "_" + TimeToString(arrowTime, TIME_SECONDS);
if(!ObjectCreate(0, objName, OBJ_ARROW, 0, arrowTime, arrowPrice))
return;
int arrowCode = (dir == "down") ? 234 : 233; // 233 = up, 234 = down
color arrowColor = (dir == "down") ? clrRed : clr;
ObjectSetInteger(0, objName, OBJPROP_ARROWCODE, arrowCode);
ObjectSetInteger(0, objName, OBJPROP_COLOR, arrowColor);
ObjectSetInteger(0, objName, OBJPROP_WIDTH, size);
ObjectSetInteger(0, objName, OBJPROP_BACK, false);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double StandartFunctions::CalculateLotByBalance()
{
// 1) Get current account balance
double balance = AccountInfoDouble(ACCOUNT_BALANCE);
// 2) Compute how many  $100 increments
int increments = int(balance / 100.0);
// e.g.: if balance=250.75 <EFBFBD>! increments = floor(250.75/100) = 2
// 3) Base lot = increments * 0.01
double lot = increments * 0.01;
// e.g.: 2 * 0.01 = 0.02
// 4) Fetch symbol s min/max/step volume
double minLot = SymbolInfoDouble(m_symbol, SYMBOL_VOLUME_MIN);
double maxLot = SymbolInfoDouble(m_symbol, SYMBOL_VOLUME_MAX);
double step = SymbolInfoDouble(m_symbol, SYMBOL_VOLUME_STEP);
// 5) If computed lot < minimum, set to minLot
if(lot < minLot)
lot = minLot;
// 6) Round  lot down to nearest multiple of  step
// e.g. if step=0.01 and lot=0.027, MathFloor(0.027/0.01)=2 <EFBFBD>! 2*0.01=0.02
if(step > 0.0)
lot = MathFloor(lot / step) * step;
// 7) If that rounding pushed lot > maxLot, clamp to maxLot
if(lot > maxLot)
lot = maxLot;
return(lot);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool StandartFunctions::CheckTradeAllowed()
{
MqlDateTime date_cur;
TimeTradeServer(date_cur);
datetime seconds_cur = date_cur.hour * 3600 + date_cur.min * 60 + date_cur.sec;
int i = 0;
while(true)
{
datetime seconds_from = {}, seconds_to = {};
if(!SymbolInfoSessionTrade(m_symbol, (ENUM_DAY_OF_WEEK)date_cur.day_of_week, i, seconds_from, seconds_to))
break;
if(seconds_cur > seconds_from && seconds_cur < seconds_to)
return true;
++i;
}
return false;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void StandartFunctions::UpdatePosition(double trailingPips,double target)
{
int total = PositionsTotal();
for(int i = total-1; i >= 0; i--)
{
ulong position_ticket = PositionGetTicket(i);
string m_pair = "";
double m_lot = 0.0;
double m_profit = 0.0;
double m_stopLoos = 0.0;
double m_open_price = 0.0;
double m_tp = 0.0;
long m_position_type;
long magic;
double m_point;
double m_bid;
double m_ask;
if(
!PositionGetString(POSITION_SYMBOL,m_pair) ||
!PositionGetDouble(POSITION_VOLUME,m_lot) ||
!PositionGetDouble(POSITION_PROFIT,m_profit)||
!PositionGetDouble(POSITION_PRICE_OPEN,m_open_price)||
!PositionGetInteger(POSITION_MAGIC,magic)||
!PositionGetDouble(POSITION_TP,m_tp)||
!PositionGetDouble(POSITION_SL,m_stopLoos))
{
return;
Print("POSITION_SYMBOL ERROR");
}
if(m_symbol != m_pair && m_magic != magic)
return;
if(
!SymbolInfoDouble(m_pair, SYMBOL_BID,m_bid)||
!SymbolInfoDouble(m_pair, SYMBOL_ASK,m_ask)||
!SymbolInfoDouble(m_pair, SYMBOL_POINT,m_point))
{
return;
Print("SYMBOL_DIGITS ERROR");
}
if(!PositionGetInteger(POSITION_TYPE,m_position_type))
{
return;
Print("POSITION_TYPE ERROR");
}
string m_position_name = m_position_type == POSITION_TYPE_BUY ? "BUY" :m_position_type == POSITION_TYPE_SELL ? "SELL" : "UNKOWN";
if(m_position_name == "UNKOWN")
{
Print("POSITION_TYPE ERROR");
return;
}
NormalizeDouble(m_bid,(int)m_digits);
NormalizeDouble(m_ask,(int)m_digits);
NormalizeDouble(m_profit,(int)m_digits);
NormalizeDouble(m_stopLoos,(int)m_digits);
NormalizeDouble(m_tp,(int)m_digits);
NormalizeDouble(m_open_price,(int)m_digits);
//double close = Close(1,m_pair,PERIOD_M5);
double buy_stop = m_bid - trailingPips ;
double sell_stop = m_ask + trailingPips ;
//double atr = tr(0,m_pair,PERIOD_H1);
//Print(
// StringFormat(
// "Pair:%s,Position:%s,Open:%.2f,Profit:%-.*f,StopLoos:%.2f,Lot:%.2f",
// m_pair,m_position_name,m_open_price,m_digits,m_profit,m_stopLoos,m_lot)
//);
//Print(StringFormat("buy:%-.*f,sell:%-.*f,m_avg:%.2f,latAvg:%.2f",m_digits,buy_stop,m_digits,sell_stop,m_avg,m_lastAvg));
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
{
if(m_profit >= target)
{
double dollarToPip =
NormalizeDouble(CalculatePipsFromDollars(m_profit,m_lot),(int)m_digits);
//m_trade.PositionClose(position_ticket);
}
if(buy_stop > m_stopLoos && buy_stop > m_open_price)
{
if(m_trade.PositionModify(position_ticket,buy_stop,m_tp))
Print("PositionModify");
else
Print(_LastError);
}
//if(m_profit >= trailingPips*3)
// m_trade.PositionClose(position_ticket);
}
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
{
if(m_profit >= target)
{
double dollarToPip =
NormalizeDouble(CalculatePipsFromDollars(m_profit,m_lot),(int)m_digits);
//m_trade.PositionClose(position_ticket);
}
if(m_stopLoos == 0)
{
if(sell_stop < m_open_price)
{
if(m_trade.PositionModify(position_ticket,sell_stop,m_tp))
Print("PositionModify");
else
Print(_LastError);
}
}
else
if(sell_stop < m_stopLoos && sell_stop < m_open_price)
{
if(m_trade.PositionModify(position_ticket,sell_stop,m_tp))
Print("PositionModify");
else
Print(_LastError);
}
//if(m_profit >= trailingPips*3)
// m_trade.PositionClose(position_ticket);
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double StandartFunctions::CalcLots(double slPoints)
{
double risk = AccountInfoDouble(ACCOUNT_BALANCE) * 10 / 100;
double ticksize = SymbolInfoDouble(m_symbol,SYMBOL_TRADE_TICK_SIZE);
double tickvalue = SymbolInfoDouble(m_symbol,SYMBOL_TRADE_TICK_VALUE);
double lotstep = SymbolInfoDouble(m_symbol,SYMBOL_VOLUME_STEP);
double moneyPerLotstep = slPoints / ticksize * tickvalue * lotstep;
double lots = MathFloor(risk / moneyPerLotstep) * lotstep;
lots = MathMin(lots,SymbolInfoDouble(m_symbol,SYMBOL_VOLUME_MAX));
lots = MathMax(lots,SymbolInfoDouble(m_symbol,SYMBOL_VOLUME_MIN));
return lots;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double StandartFunctions::CalculatePipsFromDollars(double dollarAmount,double lotSize)
{
double tickSize = SymbolInfoDouble(m_symbol, SYMBOL_TRADE_TICK_SIZE);
double tickValue = SymbolInfoDouble(m_symbol, SYMBOL_TRADE_TICK_VALUE);
double point = SymbolInfoDouble(m_symbol, SYMBOL_POINT);
int digits = (int)SymbolInfoInteger(m_symbol, SYMBOL_DIGITS);
double pipValue = tickValue / tickSize * point;
double pips = dollarAmount / (pipValue * lotSize);
return pips;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool StandartFunctions::IsPivotHigh(int index,int Left,int Right,const MqlRates &rates[])
{
for(int j = 1; j <= Right; j++)
if(rates[index].high <= rates[index - j].high)
return false;
for(int j = 1; j <= Right; j++)
if(rates[index].high <= rates[index + j].high)
return false;
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool StandartFunctions::IsPivotLow(int index,int Left,int Right,const MqlRates &rates[])
{
for(int j = 1; j <= Left; j++)
if(rates[index].low >= rates[index - j].low)
return false;
for(int j = 1; j <= Right; j++)
if(rates[index].low>= rates[index + j].low)
return false;
return true;
}
//+------------------------------------------------------------------+
int PipsToPoint(string symbol,double pips)
{
int D = (int) SymbolInfoInteger(symbol,SYMBOL_DIGITS);
return (int)(pips* ((D==3 || D==5) ? 10 : 1));
}
//+------------------------------------------------------------------+
double PointsToDouble(string symbol,double point)
{
Print(SymbolInfoDouble(symbol,SYMBOL_POINT));
return (point * SymbolInfoDouble(symbol,SYMBOL_POINT));
}
//+------------------------------------------------------------------+
bool CanOpenOrder(string symbol,ENUM_ORDER_TYPE OrderType,double lot,double entry)
{
double margin = 0.0;
if(!OrderCalcMargin(OrderType, symbol, lot, entry, margin))
{
return false;
}
double freeMargin = AccountInfoDouble(ACCOUNT_MARGIN_FREE);
if(margin > freeMargin)
{
return false;
}
return true;
}
//+------------------------------------------------------------------+