//+------------------------------------------------------------------+ //| PositionInfo.mqh | //| Copyright 2009-2020, MetaQuotes Software Corp. | //| http://www.mql5.com | //| Copyright 2022, Yuriy Bykov | //| https://www.mql5.com/ru/code/38861 | //| https://www.mql5.com/en/code/39161 | //+------------------------------------------------------------------+ #property copyright "Copyright 2022, Yuriy Bykov" #property link "https://www.mql5.com/ru/users/antekov" #property version "1.00" #property strict #ifdef __MQL4__ enum ENUM_POSITION_TYPE { POSITION_TYPE_BUY, POSITION_TYPE_SELL, }; enum ENUM_ACCOUNT_MARGIN_MODE { ACCOUNT_MARGIN_MODE_RETAIL_NETTING, ACCOUNT_MARGIN_MODE_EXCHANGE, ACCOUNT_MARGIN_MODE_RETAIL_HEDGING }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int PositionsTotal() { return OrdersTotal(); } #include //+------------------------------------------------------------------+ //| Class CPositionInfo. | //| Appointment: Class for access to position info. | //| Derives from class CObject. | //+------------------------------------------------------------------+ class CPositionInfo : public CObject { protected: ENUM_POSITION_TYPE m_type; double m_volume; double m_price; double m_stop_loss; double m_take_profit; public: CPositionInfo(void); ~CPositionInfo(void); //--- fast access methods to the integer position propertyes ulong Ticket(void) const; datetime Time(void) const; ulong TimeMsc(void) const; datetime TimeUpdate(void) const; ulong TimeUpdateMsc(void) const; ENUM_POSITION_TYPE PositionType(void) const; string TypeDescription(void) const; long Magic(void) const; long Identifier(void) const; //--- fast access methods to the double position propertyes double Volume(void) const; double PriceOpen(void) const; double StopLoss(void) const; double TakeProfit(void) const; double PriceCurrent(void) const; double Commission(void) const; double Swap(void) const; double Profit(void) const; //--- fast access methods to the string position propertyes string Symbol(void) const; string Comment(void) const; //--- access methods to the API MQL5 functions //bool InfoInteger(const ENUM_POSITION_PROPERTY_INTEGER prop_id,long &var) const; //bool InfoDouble(const ENUM_POSITION_PROPERTY_DOUBLE prop_id,double &var) const; //bool InfoString(const ENUM_POSITION_PROPERTY_STRING prop_id,string &var) const; //--- info methods string FormatType(string &str, const uint type) const; string FormatPosition(string &str) const; //--- methods for select position bool Select(const string symbol); bool SelectByMagic(const string symbol, const ulong magic); bool SelectByTicket(const ulong ticket); bool SelectByIndex(const int index); //--- void StoreState(void); bool CheckState(void); int CountType(ENUM_ORDER_TYPE type,long magic); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CPositionInfo::CPositionInfo(void) : m_type(WRONG_VALUE), m_volume(0.0), m_price(0.0), m_stop_loss(0.0), m_take_profit(0.0) { } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CPositionInfo::~CPositionInfo(void) { } int CPositionInfo::CountType(ENUM_ORDER_TYPE type,long magic){ int result = 0; int count = OrdersTotal(); for(int i=count-1; i>=0; i--){ if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue; if(OrderSymbol()==Symbol() && OrderMagicNumber()==magic && (OrderType()==type || type == -1)) result++; } return(result); } //+------------------------------------------------------------------+ //| Get the property value "POSITION_TICKET" | //+------------------------------------------------------------------+ ulong CPositionInfo::Ticket(void) const { return((ulong)OrderTicket()); } //+------------------------------------------------------------------+ //| Get the property value "POSITION_TIME" | //+------------------------------------------------------------------+ datetime CPositionInfo::Time(void) const { return((datetime)OrderOpenTime()); } //+------------------------------------------------------------------+ //| Get the property value "POSITION_TIME_MSC" | //+------------------------------------------------------------------+ ulong CPositionInfo::TimeMsc(void) const { return((ulong)OrderOpenTime()); } //+------------------------------------------------------------------+ //| Get the property value "POSITION_TIME_UPDATE" | //+------------------------------------------------------------------+ datetime CPositionInfo::TimeUpdate(void) const { return((datetime)OrderOpenTime()); } //+------------------------------------------------------------------+ //| Get the property value "POSITION_TIME_UPDATE_MSC" | //+------------------------------------------------------------------+ ulong CPositionInfo::TimeUpdateMsc(void) const { return((ulong)OrderOpenTime()); } //+------------------------------------------------------------------+ //| Get the property value "POSITION_TYPE" | //+------------------------------------------------------------------+ ENUM_POSITION_TYPE CPositionInfo::PositionType(void) const { return((ENUM_POSITION_TYPE)OrderType()); } //+------------------------------------------------------------------+ //| Get the property value "POSITION_TYPE" as string | //+------------------------------------------------------------------+ string CPositionInfo::TypeDescription(void) const { string str; //--- return(FormatType(str, PositionType())); } //+------------------------------------------------------------------+ //| Get the property value "POSITION_MAGIC" | //+------------------------------------------------------------------+ long CPositionInfo::Magic(void) const { return(OrderMagicNumber()); } //+------------------------------------------------------------------+ //| Get the property value "POSITION_IDENTIFIER" | //+------------------------------------------------------------------+ long CPositionInfo::Identifier(void) const { return(OrderTicket()); } //+------------------------------------------------------------------+ //| Get the property value "POSITION_VOLUME" | //+------------------------------------------------------------------+ double CPositionInfo::Volume(void) const { return(OrderLots()); } //+------------------------------------------------------------------+ //| Get the property value "POSITION_PRICE_OPEN" | //+------------------------------------------------------------------+ double CPositionInfo::PriceOpen(void) const { return(OrderOpenPrice()); } //+------------------------------------------------------------------+ //| Get the property value "POSITION_SL" | //+------------------------------------------------------------------+ double CPositionInfo::StopLoss(void) const { return(OrderStopLoss()); } //+------------------------------------------------------------------+ //| Get the property value "POSITION_TP" | //+------------------------------------------------------------------+ double CPositionInfo::TakeProfit(void) const { return(OrderTakeProfit()); } //+------------------------------------------------------------------+ //| Get the property value "POSITION_PRICE_CURRENT" | //+------------------------------------------------------------------+ double CPositionInfo::PriceCurrent(void) const { return -1; return(OrderType() == ORDER_TYPE_BUY ? Bid : Ask); } //+------------------------------------------------------------------+ //| Get the property value "POSITION_COMMISSION" | //+------------------------------------------------------------------+ double CPositionInfo::Commission(void) const { return(OrderCommission()); } //+------------------------------------------------------------------+ //| Get the property value "POSITION_SWAP" | //+------------------------------------------------------------------+ double CPositionInfo::Swap(void) const { return(OrderSwap()); } //+------------------------------------------------------------------+ //| Get the property value "POSITION_PROFIT" | //+------------------------------------------------------------------+ double CPositionInfo::Profit(void) const { return(OrderProfit()); } //+------------------------------------------------------------------+ //| Get the property value "POSITION_SYMBOL" | //+------------------------------------------------------------------+ string CPositionInfo::Symbol(void) const { return(OrderSymbol()); } //+------------------------------------------------------------------+ //| Get the property value "POSITION_COMMENT" | //+------------------------------------------------------------------+ string CPositionInfo::Comment(void) const { return(OrderComment()); } /* //+------------------------------------------------------------------+ //| Access functions PositionGetInteger(...) | //+------------------------------------------------------------------+ bool CPositionInfo::InfoInteger(const ENUM_POSITION_PROPERTY_INTEGER prop_id,long &var) const { return(PositionGetInteger(prop_id,var)); } //+------------------------------------------------------------------+ //| Access functions PositionGetDouble(...) | //+------------------------------------------------------------------+ bool CPositionInfo::InfoDouble(const ENUM_POSITION_PROPERTY_DOUBLE prop_id,double &var) const { return(PositionGetDouble(prop_id,var)); } //+------------------------------------------------------------------+ //| Access functions PositionGetString(...) | //+------------------------------------------------------------------+ bool CPositionInfo::InfoString(const ENUM_POSITION_PROPERTY_STRING prop_id,string &var) const { return(PositionGetString(prop_id,var)); } */ //+------------------------------------------------------------------+ //| Converts the position type to text | //+------------------------------------------------------------------+ string CPositionInfo::FormatType(string &str, const uint type) const { //--- see the type switch(type) { case POSITION_TYPE_BUY: str = "buy"; break; case POSITION_TYPE_SELL: str = "sell"; break; default: str = "unknown position type " + (string)type; } //--- return the result return(str); } //+------------------------------------------------------------------+ //| Converts the position parameters to text | //+------------------------------------------------------------------+ string CPositionInfo::FormatPosition(string &str) const { string tmp, type; long tmp_long; ENUM_ACCOUNT_MARGIN_MODE margin_mode = ACCOUNT_MARGIN_MODE_RETAIL_HEDGING; //--- set up string symbol_name = this.Symbol(); int digits = _Digits; if(SymbolInfoInteger(symbol_name, SYMBOL_DIGITS, tmp_long)) digits = (int)tmp_long; //--- form the position description if(margin_mode == ACCOUNT_MARGIN_MODE_RETAIL_HEDGING) str = StringFormat("#%I64u %s %s %s %s", Ticket(), FormatType(type, PositionType()), DoubleToString(Volume(), 2), symbol_name, DoubleToString(PriceOpen(), digits + 3)); else str = StringFormat("%s %s %s %s", FormatType(type, PositionType()), DoubleToString(Volume(), 2), symbol_name, DoubleToString(PriceOpen(), digits + 3)); //--- add stops if there are any double sl = StopLoss(); double tp = TakeProfit(); if(sl != 0.0) { tmp = StringFormat(" sl: %s", DoubleToString(sl, digits)); str += tmp; } if(tp != 0.0) { tmp = StringFormat(" tp: %s", DoubleToString(tp, digits)); str += tmp; } //--- return the result return(str); } /* //+------------------------------------------------------------------+ //| Access functions PositionSelect(...) | //+------------------------------------------------------------------+ bool CPositionInfo::Select(const string symbol) { return(PositionSelect(symbol)); } //+------------------------------------------------------------------+ //| Access functions PositionSelect(...) | //+------------------------------------------------------------------+ bool CPositionInfo::SelectByMagic(const string symbol,const ulong magic) { bool res=false; uint total=PositionsTotal(); //--- for(uint i=0; i 0); } //+------------------------------------------------------------------+ //| Select a position on the index | //+------------------------------------------------------------------+ bool CPositionInfo::SelectByIndex(const int index) { if(OrderSelect(index, SELECT_BY_POS, MODE_TRADES)) { int type = OrderType(); if(type < 2) { return(true); } } return(false); } //+------------------------------------------------------------------+ //| Stored position's current state | //+------------------------------------------------------------------+ void CPositionInfo::StoreState(void) { m_type = PositionType(); m_volume = Volume(); m_price = PriceOpen(); m_stop_loss = StopLoss(); m_take_profit = TakeProfit(); } //+------------------------------------------------------------------+ //| Check position change | //+------------------------------------------------------------------+ bool CPositionInfo::CheckState(void) { if(m_type == PositionType() && m_volume == Volume() && m_price == PriceOpen() && m_stop_loss == StopLoss() && m_take_profit == TakeProfit()) return(false); //--- return(true); } //+------------------------------------------------------------------+ #endif //+------------------------------------------------------------------+