Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // hyrStatus.mqh for MT5
- // by Copyright 2026 hyrolean
- //---------------------------------------------------------------------------
- // Local:: <DataFolder>\MQL5\Include\User\hyrStatus.mqh
- // URL:: https://pastebin.com/d9Z8P2qD
- // Date:: 2026/05/01
- //---------------------------------------------------------------------------
- #include <Arrays/ArrayObj.mqh>
- #include <Trade/PositionInfo.mqh>
- #include <Trade/OrderInfo.mqh>
- #include <Trade/DealInfo.mqh>
- //---------------------------------------------------------------------------
- //状態チェック
- //-----
- enum ENUM_ORDERSORT {
- ORDERSORT_NONE=0,
- ORDERSORT_PRICE_ASCEND,
- ORDERSORT_PRICE_DESCEND,
- ORDERSORT_OPENTIME_ASCEND,
- ORDERSORT_OPENTIME_DESCEND,
- ORDERSORT_STOPLOSS_ASCEND,
- ORDERSORT_STOPLOSS_DESCEND
- };
- class COrderStatus : public CObject
- {
- private:
- static int inline DblComp(double v1, double v2) {
- if(v1==v2) return 0 ;
- return v1<v2 ? -1 : +1 ;
- }
- public:
- ulong Ticket;
- double Price;
- double Stoploss;
- double Takeprofit;
- double Lots;
- double Profit;
- double Commission;
- double Swap;
- datetime OpenTime;
- datetime Expiration;
- string Comment;
- double BorderPrice;
- double BorderPriceWithSwap;
- double InitialPrice;
- double InitialLots;
- double InitialCommission;
- string InitialComment;
- datetime InitialTime;
- double InitialBorderPrice;
- double DealtLots;
- double DealtProfit;
- double DealtCommission;
- double DealtSwap;
- int DealtCount;
- int Tag;
- COrderStatus() : CObject() {
- Ticket = 0 ;
- Price = Stoploss = Takeprofit = Lots = Profit = 0.0 ;
- InitialPrice = InitialLots = 0.0 ;
- BorderPrice = BorderPriceWithSwap = InitialBorderPrice = 0.0 ;
- Commission = Swap = InitialCommission = 0.0 ;
- DealtLots = DealtProfit = DealtCommission = DealtSwap = 0.0 ; DealtCount=0 ;
- OpenTime = Expiration = InitialTime = 0 ;
- Comment = InitialComment = "" ;
- Tag = 0 ;
- }
- COrderStatus(
- ulong Ticket_,
- double Price_,
- double Stoploss_,
- double Takeprofit_,
- double Lots_,
- double Profit_,
- datetime OpenTime_,
- string Comment_,
- int Tag_=0 ) : CObject() {
- Ticket = Ticket_;
- Price = InitialPrice = Price_;
- Stoploss = Stoploss_;
- Takeprofit = Takeprofit_;
- Lots = InitialLots = Lots_;
- Profit = Profit_;
- OpenTime = InitialTime = OpenTime_;
- Comment = InitialComment = Comment_;
- Tag = Tag_ ;
- BorderPrice = BorderPriceWithSwap = InitialBorderPrice = Price;
- DealtLots = DealtProfit = DealtCommission = DealtSwap = 0.0 ; DealtCount=0 ;
- Commission = Swap = InitialCommission = 0.0 ;
- }
- virtual int Compare(const CObject *node,const int mode=0) const {
- COrderStatus *status = (COrderStatus*) node ;
- switch(mode) {
- case ORDERSORT_PRICE_ASCEND:
- return DblComp(Price,status.Price);
- case ORDERSORT_PRICE_DESCEND:
- return DblComp(status.Price,Price);
- case ORDERSORT_OPENTIME_ASCEND:
- return DblComp(OpenTime,status.OpenTime);
- case ORDERSORT_OPENTIME_DESCEND:
- return DblComp(status.OpenTime,OpenTime);
- case ORDERSORT_STOPLOSS_ASCEND:
- return DblComp(Stoploss,status.Stoploss);
- case ORDERSORT_STOPLOSS_DESCEND:
- return DblComp(status.Stoploss,Stoploss);
- }
- return 0;
- }
- };
- //-----
- class STATUS {
- private:
- void Init() {
- HalfSpread = 0.0 ;
- Bid = 0.0; Ask = 0.0 ;
- Positions = 0 ;
- PyramidPositions = 0 ;
- AveragePositions = 0 ;
- MinPrice = DBL_MAX ;
- MaxPrice = 0.0 ;
- MinPriceLots = 0.0 ;
- MaxPriceLots = 0.0 ;
- MinPriceProfit = 0.0 ;
- MaxPriceProfit = 0.0 ;
- MinPriceStoploss = 0.0 ;
- MaxPriceStoploss = 0.0 ;
- MinPriceTicket = 0 ;
- MaxPriceTicket = 0 ;
- MinStoploss = DBL_MAX ;
- MaxStoploss = 0.0 ;
- MinTakeprofit = DBL_MAX ;
- MaxTakeprofit = 0.0 ;
- MinLots = DBL_MAX ;
- MaxLots = 0.0 ;
- MinOpenTime = TimeCurrent() ;
- MaxOpenTime = 0 ;
- PyramidMinLots = DBL_MAX ;
- PyramidMaxLots = 0.0 ;
- AverageMinLots = DBL_MAX ;
- AverageMaxLots = 0.0 ;
- BorderPrice = 0.0 ;
- TotalPrices = 0.0 ;
- TotalLots = 0.0 ;
- GrossProfit = 0.0 ;
- PositiveProfit = 0.0 ;
- CurrentPrices = 0.0 ;
- MedianPrices = 0.0 ;
- Tag = 0 ;
- Orders.Clear();
- }
- void Append(COrderStatus *Order) {
- double realProfit = Order.Profit + Order.Commission + Order.Swap ;
- GrossProfit += realProfit;
- if(realProfit>0.0)
- PositiveProfit += realProfit;
- if(Order.Price<MinPrice) {
- MinPrice = Order.Price ;
- MinPriceLots = Order.Lots ;
- MinPriceProfit = Order.Profit ;
- MinPriceStoploss = Order.Stoploss ;
- MinPriceTicket = Order.Ticket ;
- }
- if(Order.Price>MaxPrice) {
- MaxPrice = Order.Price ;
- MaxPriceLots = Order.Lots ;
- MaxPriceProfit = Order.Profit ;
- MaxPriceStoploss = Order.Stoploss ;
- MaxPriceTicket = Order.Ticket ;
- }
- if(Order.Stoploss<MinStoploss) MinStoploss = Order.Stoploss;
- if(Order.Stoploss>MaxStoploss) MaxStoploss = Order.Stoploss;
- if(Order.Takeprofit<MinTakeprofit) MinTakeprofit = Order.Takeprofit;
- if(Order.Takeprofit>MaxTakeprofit) MaxTakeprofit = Order.Takeprofit;
- if(Order.Lots<MinLots) MinLots = Order.Lots;
- if(Order.Lots>MaxLots) MaxLots = Order.Lots;
- TotalPrices += Order.BorderPrice*Order.Lots ;
- TotalLots += Order.Lots;
- if(Flag==FLAG_BUY) {
- CurrentPrices += (Bid - Order.BorderPrice) * Order.Lots ;
- MedianPrices += (Order.BorderPrice + HalfSpread) * Order.Lots ;
- }
- else if(Flag==FLAG_SELL) {
- CurrentPrices += (Order.BorderPrice - Ask) * Order.Lots ;
- MedianPrices += (Order.BorderPrice - HalfSpread) * Order.Lots ;
- }
- if(MaxOpenTime<Order.OpenTime) MaxOpenTime=Order.OpenTime;
- if(MinOpenTime>Order.OpenTime) MinOpenTime=Order.OpenTime;
- if(StringFind(Order.InitialComment,"PRMD")>=0||
- StringFind(Order.Comment,"PRMD")>=0) {
- if(Order.Lots>PyramidMaxLots)
- PyramidMaxLots = Order.Lots ;
- if(Order.Lots<PyramidMinLots)
- PyramidMinLots = Order.Lots ;
- PyramidPositions++;
- }
- if(StringFind(Order.InitialComment,"AVRG")>=0||
- StringFind(Order.Comment,"AVRG")>=0) {
- if(Order.Lots>AverageMaxLots)
- AverageMaxLots = Order.Lots ;
- if(Order.Lots<AverageMinLots)
- AverageMinLots = Order.Lots ;
- AveragePositions++;
- }
- Positions++;
- }
- void Finish() {
- if(OrdersLastSort!=ORDERSORT_NONE)
- Orders.Sort(OrdersLastSort);
- if(TotalLots>0) {
- BorderPrice = TotalPrices / TotalLots ;
- }
- }
- protected:
- CArrayObj *Orders;
- ENUM_ORDERSORT OrdersLastSort;
- virtual void CheckInit() { Init() ; }
- virtual void CheckOrder(COrderStatus *OrderStatus) { Append(OrderStatus); }
- virtual void CheckFinish() { Finish() ; }
- protected:
- CPositionInfo PosInfo;
- COrderInfo OrdInfo;
- CDealInfo DealInfo;
- int AnalyzeDealt(COrderStatus *orderStatus) {
- int dealtCount=0;
- if(HistorySelectByPosition(orderStatus.Ticket)) {
- int total = HistoryDealsTotal();
- for(int i=0; i<total; i++) {
- TICKET dealtTicket = HistoryDealGetTicket(i);
- if(dealtTicket > 0) {
- DealInfo.Ticket(dealtTicket);
- ENUM_DEAL_ENTRY entryType = DealInfo.Entry() ;
- if(entryType==DEAL_ENTRY_IN) {
- orderStatus.InitialPrice = DealInfo.Price();
- orderStatus.InitialTime = DealInfo.Time();
- orderStatus.InitialLots = DealInfo.Volume();
- orderStatus.InitialCommission = DealInfo.Commission();
- orderStatus.InitialComment = DealInfo.Comment();
- }else {
- if( entryType == DEAL_ENTRY_OUT || entryType == DEAL_ENTRY_INOUT) {
- orderStatus.DealtLots += DealInfo.Volume();
- dealtCount++;
- }
- orderStatus.DealtProfit += DealInfo.Profit();
- orderStatus.DealtCommission += DealInfo.Commission();
- orderStatus.DealtSwap += DealInfo.Swap();
- }
- }
- }
- }
- return dealtCount ;
- }
- public:
- string USDJPYFindSymbol() {
- if(SymbolUSDJPY=="") {
- int total = SymbolsTotal(false);
- for(int i = 0; i < total; i++) {
- string name = SymbolName(i, false);
- if(StringFind(name, "USDJPY") >= 0) {
- SymbolUSDJPY = name; break;
- }
- }
- }
- if(SymbolUSDJPY!="") SymbolSelect(SymbolUSDJPY, true);
- return SymbolUSDJPY ;
- }
- double USDJPYRateAt(datetime time) {
- MqlTick ticks[];
- ulong tick = time * 1000 ;
- //ティックからrateを拾ってくる
- if(CopyTicks(USDJPYFindSymbol(),ticks,COPY_TICKS_ALL,tick,1)==1)
- return ticks[0].bid ;
- return 0.0;
- }
- double USDJPYCommissionPerLotAt(datetime time) {
- //USDJPYFindSymbol();
- string currency = AccountInfoString(ACCOUNT_CURRENCY);
- double commission = 0;
- if(currency == "JPY") {
- commission += CommissionPerLotJPY ;
- if(CommissionPerLotUSD!=0.0) {
- commission += CommissionPerLotUSD * USDJPYRateAt(time);
- }
- }else if(currency == "USD") {
- commission += CommissionPerLotUSD ;
- if(CommissionPerLotJPY!=0.0) {
- double rate = USDJPYRateAt(time);
- if(rate>0.0) // 0 div 回避
- commission += CommissionPerLotJPY / rate ;
- }
- }
- return commission ;
- }
- public:
- OP Type;
- FLAG Flag;
- long Magic;
- double CommissionPerLotJPY;
- double CommissionPerLotUSD;
- string SymbolUSDJPY;
- double Bid,Ask,Spread,HalfSpread;
- int Positions, PyramidPositions, AveragePositions;
- double MinPrice, MaxPrice, BorderPrice;
- double MinPriceLots, MaxPriceLots;
- double MinPriceProfit, MaxPriceProfit;
- double MinPriceStoploss, MaxPriceStoploss;
- ulong MinPriceTicket, MaxPriceTicket;
- double MinStoploss, MaxStoploss;
- double MinTakeprofit, MaxTakeprofit;
- double MinLots, MaxLots;
- datetime MinOpenTime, MaxOpenTime;
- double PyramidMinLots, PyramidMaxLots;
- double AverageMinLots, AverageMaxLots;
- double TotalPrices, TotalLots;
- double CurrentPrices, MedianPrices;
- double GrossProfit;
- double PositiveProfit;
- int Tag;
- STATUS(OP Type_=OP_BUY, long Magic_=0,
- double CommissionPerLotJPY_=0, double CommissionPerLotUSD_=0, string SymbolUSDJPY_="") {
- Orders = new CArrayObj();
- Init();
- Type=Type_;
- Flag=OpToFlag(Type);
- Magic=Magic_;
- CommissionPerLotJPY = CommissionPerLotJPY_>0? -CommissionPerLotJPY_: CommissionPerLotJPY_ ;
- CommissionPerLotUSD = CommissionPerLotUSD_>0? -CommissionPerLotUSD_: CommissionPerLotUSD_ ;
- SymbolUSDJPY = SymbolUSDJPY_ ;
- OrdersLastSort=ORDERSORT_NONE;
- }
- ~STATUS() {
- delete Orders;
- }
- virtual void Check(ENUM_POSITION_TYPE type, long magic) {
- Type=(OP)type;
- Flag=OpToFlag(Type);
- Magic=magic;
- CheckInit();
- Ask = SymbolInfoDouble(_Symbol,SYMBOL_ASK) ;
- Bid = SymbolInfoDouble(_Symbol,SYMBOL_BID) ;
- Spread = Ask-Bid ;
- HalfSpread = Spread/2.0;
- double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
- double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
- for(int i=PositionsTotal()-1 ; i>=0 ; i--) {
- if( PosInfo.SelectByIndex(i) && PosInfo.Symbol() == _Symbol ) {
- if(magic==PosInfo.Magic()) {
- if(type==PosInfo.PositionType()) {
- ulong orderTicket = PosInfo.Ticket() ;
- double orderPrice = PosInfo.PriceOpen();
- double orderStoploss = PosInfo.StopLoss();
- double orderTakeprofit = PosInfo.TakeProfit();
- double orderLots = PosInfo.Volume();
- double orderProfit = PosInfo.Profit() ;
- datetime orderOpenTime = PosInfo.Time() ;
- string orderComment = PosInfo.Comment();
- COrderStatus *orderStatus = new COrderStatus(
- orderTicket,
- orderPrice,
- orderStoploss,
- orderTakeprofit,
- orderLots,
- orderProfit,
- orderOpenTime,
- orderComment ) ;
- orderStatus.Commission = PosInfo.Commission();
- orderStatus.Swap = PosInfo.Swap();
- orderStatus.DealtCount = AnalyzeDealt(orderStatus);
- if(orderStatus.InitialLots==0.0) {
- orderStatus.InitialLots=orderStatus.Lots+orderStatus.DealtLots;
- }
- if(CommissionPerLotJPY!=0||CommissionPerLotUSD!=0) {
- // ※手数料が定義されている場合は、手数料を上書きする
- double commissionPerLot = USDJPYCommissionPerLotAt(orderStatus.OpenTime) ;
- orderStatus.InitialCommission = commissionPerLot * orderStatus.InitialLots ;
- orderStatus.Commission = commissionPerLot * orderStatus.Lots ;
- }
- if(orderStatus.Commission==0.0) {
- orderStatus.Commission = orderStatus.InitialCommission*orderStatus.Lots/orderStatus.InitialLots ;
- }
- if(orderStatus.InitialCommission!=0.0) {
- double debt = MathMin(orderStatus.InitialCommission, 0.0) ;
- if(Flag==FLAG_BUY) // [-] -> [+]
- debt = -debt ;
- double costsPerPoint = orderStatus.InitialLots * tickValue ;
- orderStatus.InitialBorderPrice += (debt/costsPerPoint)*_Point ;
- orderStatus.InitialBorderPrice
- = NormalizeDouble(orderStatus.InitialBorderPrice, _Digits);
- }
- if(orderStatus.Commission!=0.0||orderStatus.Swap!=0.0) {
- double debt = MathMin(orderStatus.Commission, 0.0) ;
- double debtWithSwap = MathMin(orderStatus.Swap+debt, 0.0) ;
- if(Flag==FLAG_BUY) { // [-] -> [+]
- debt = -debt ;
- debtWithSwap = -debtWithSwap ;
- }
- double costsPerPoint = orderLots * tickValue ;
- orderStatus.BorderPriceWithSwap += (debtWithSwap/costsPerPoint)*_Point ;
- orderStatus.BorderPriceWithSwap = NormalizeDouble(orderStatus.BorderPriceWithSwap,_Digits);
- orderStatus.BorderPrice += (debt/costsPerPoint)*_Point ;
- orderStatus.BorderPrice = NormalizeDouble(orderStatus.BorderPrice,_Digits);
- }
- Orders.Add(orderStatus);
- CheckOrder(orderStatus);
- }
- }
- }
- }
- CheckFinish();
- }
- virtual void CheckReserved(ENUM_ORDER_TYPE type, long magic) {
- Type=(OP)type;
- Flag=OpToFlag(Type);
- Magic=magic;
- CheckInit();
- Ask = SymbolInfoDouble(_Symbol,SYMBOL_ASK) ;
- Bid = SymbolInfoDouble(_Symbol,SYMBOL_BID) ;
- Spread = Ask-Bid ;
- HalfSpread = Spread/2.0;
- for(int i=OrdersTotal()-1 ; i>=0 ; i--) {
- if( OrdInfo.SelectByIndex(i) && OrdInfo.Symbol() == _Symbol ) {
- if(magic==OrdInfo.Magic()) {
- if(type==OrdInfo.OrderType()) {
- ulong orderTicket = OrdInfo.Ticket() ;
- double orderPrice = OrdInfo.PriceOpen();
- double orderStoploss = OrdInfo.StopLoss();
- double orderTakeprofit = OrdInfo.TakeProfit();
- double orderLots = OrdInfo.VolumeInitial();
- double orderProfit = 0 ;
- datetime orderSetupTime = OrdInfo.TimeSetup();
- datetime orderExpiration = OrdInfo.TimeExpiration();
- string orderComment = OrdInfo.Comment();
- COrderStatus *orderStatus = new COrderStatus(
- orderTicket,
- orderPrice,
- orderStoploss,
- orderTakeprofit,
- orderLots,
- orderProfit,
- orderSetupTime,
- orderComment ) ;
- orderStatus.Expiration = orderExpiration ;
- Orders.Add(orderStatus);
- CheckOrder(orderStatus);
- }
- }
- }
- }
- CheckFinish();
- }
- void OrdersSort(ENUM_ORDERSORT mode) {
- if(mode!=ORDERSORT_NONE&&mode!=OrdersLastSort)
- Orders.Sort(mode);
- OrdersLastSort = mode ;
- }
- int OrdersCount() const { return Orders.Total(); }
- COrderStatus *OrdersAt(int index) const
- { return (COrderStatus*) Orders.At(index); }
- int OrdersRange(const COrderStatus *Order, int &First, int &Last) const {
- if(OrdersLastSort==ORDERSORT_NONE) return -1 ;
- int first = Orders.SearchFirst(Order);
- if(first<0) return 0 ;
- int last = Orders.SearchLast(Order);
- if(last<0) return 0 ;
- First = first ;
- Last = last ;
- return Last-First+1 ;
- }
- /*
- double ProfitPrice(double borderPrice=0.0) const {
- if(borderPrice==0.0) borderPrice = BorderPrice;
- if(borderPrice>0.0) {
- //double stride = PyramidingStride * Point ;
- switch(Type) {
- case POSITION_TYPE_BUY: {
- double bar = MathMax(MaxPrice,BuyMaxPrice)-borderPrice ;
- if(bar>0.0) {
- return bar * (ProfitRatePer / 100.0) + borderPrice ;
- }
- break;
- }
- case POSITION_TYPE_SELL: {
- double bar = MathMin(MinPrice,SellMinPrice)-borderPrice ;
- if(bar<0.0) {
- return bar * (ProfitRatePer / 100.0) + borderPrice ;
- }
- break;
- }
- }
- }
- return borderPrice ;
- }
- */
- double MedianBorderPrice(const STATUS &revStatus, double lossPrices=0.0) const
- {
- double medianLots = Type==POSITION_TYPE_BUY ? TotalLots : -TotalLots ;
- medianLots += revStatus.Type==POSITION_TYPE_BUY ? revStatus.TotalLots: -revStatus.TotalLots ;
- if(Type==POSITION_TYPE_BUY?medianLots>0.0:medianLots<0.0) {
- double medianPrices = Type==POSITION_TYPE_BUY ? MedianPrices-lossPrices : -MedianPrices+lossPrices ;
- medianPrices += revStatus.Type==POSITION_TYPE_BUY ? revStatus.MedianPrices: -revStatus.MedianPrices ;
- double medianBorder = medianPrices/medianLots ;
- switch(Type) {
- case POSITION_TYPE_BUY:
- medianBorder -= HalfSpread;
- break;
- case POSITION_TYPE_SELL:
- medianBorder += HalfSpread;
- break;
- }
- return medianBorder ;
- }
- return 0.0;
- }
- };
- //-----
- int inline CheckStatus(OP type, long magic, STATUS *status, bool reserved=false)
- {
- if(!reserved) {
- switch(type) {
- case OP_BUY:
- case OP_SELL:
- status.Check((ENUM_POSITION_TYPE)type,magic);
- break;
- default:
- reserved=true ;
- }
- }
- if(reserved) {
- status.CheckReserved((ENUM_ORDER_TYPE)type,magic);
- }
- return status.Positions;
- }
- //---------------------------------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment