HLine Partial Position Fixing

Author: Copyright © 2021, Vladimir Karputov
Price Data Components
Series array that contains tick volumes of each bar
Miscellaneous
It issuies visual alerts to the screen
0 Views
0 Downloads
0 Favorites
HLine Partial Position Fixing
ÿþ//+------------------------------------------------------------------+

//|                                HLine Partial Position Fixing.mq5 |

//|                              Copyright © 2021, Vladimir Karputov |

//|                      https://www.mql5.com/en/users/barabashkakvn |

//+------------------------------------------------------------------+

#property copyright "Copyright © 2021, Vladimir Karputov"

#property link      "https://www.mql5.com/en/users/barabashkakvn"

#property version   "1.001"

/*

   barabashkakvn Trading engine 4.004

*/

#include <Trade\PositionInfo.mqh>

#include <Trade\Trade.mqh>

#include <Trade\SymbolInfo.mqh>

//---

CPositionInfo  m_position;                   // object of CPositionInfo class

CTrade         m_trade;                      // object of CTrade class

CSymbolInfo    m_symbol;                     // object of CSymbolInfo class

//+------------------------------------------------------------------+

//| Enum Fixing                                                      |

//+------------------------------------------------------------------+

enum ENUM_FIXING

  {

   percent=0,  // percent

   lot=1,      // lot

  };

//--- input parameters

input group             "Trading settings"

input ENUM_TIMEFRAMES      InpWorkingPeriod        = PERIOD_CURRENT;    // Working timeframe

input ENUM_FIXING          InpFixing               = percent;           // Type fixing: percent or lot

input double               InpVolumeFixing         = 50.0;              // The value for "Type fixing"

input string               InpHLineName            = "Partial Fixing";  // HLine Name

input group             "Additional features"

input bool                 InpPrintLog             = true;              // Print log

input ulong                InpMagic                = 10619500;          // Magic number

input int                  IntReset                = 15;                // Reset

//---

long     m_array_identifier[];                  // array ID of position

bool     m_init_error               = false;    // error on InInit

//+------------------------------------------------------------------+

//| Expert initialization function                                   |

//+------------------------------------------------------------------+

int OnInit()

  {

   Print(__FUNCTION__,", ",ArraySize(m_array_identifier));

//--- forced initialization of variables

   ArrayFree(m_array_identifier);

   m_init_error               = false;    // error on InInit

//---

   ResetLastError();

   if(!m_symbol.Name(Symbol())) // sets symbol name

     {

      Print(__FILE__," ",__FUNCTION__,", ERROR: CSymbolInfo.Name");

      return(INIT_FAILED);

     }

//---

   if(InpFixing==percent && (InpVolumeFixing>=100.0 || InpVolumeFixing<=0.0))

     {

      string err_text=(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")?

                      "@>F5=B =5 <>65B 1KBL <=0 8 =5 <>65B 1KBL >=100!":

                      "Percentage cannot be <= 0 and cannot be> = 100!";

      if(MQLInfoInteger(MQL_TESTER)) // when testing, we will only output to the log about incorrect input parameters

         Print(__FILE__," ",__FUNCTION__,", ERROR: ",err_text);

      else // if the Expert Advisor is run on the chart, tell the user about the error

         Alert(__FILE__," ",__FUNCTION__,", ERROR: ",err_text);

      //---

      m_init_error=true;

      return(INIT_SUCCEEDED);

     }

   if(InpFixing==lot)

     {

      string err_text="";

      if(!CheckVolumeValue(InpVolumeFixing,err_text))

        {

         if(MQLInfoInteger(MQL_TESTER)) // when testing, we will only output to the log about incorrect input parameters

            Print(__FILE__," ",__FUNCTION__,", ERROR: ",err_text);

         else // if the Expert Advisor is run on the chart, tell the user about the error

            Alert(__FILE__," ",__FUNCTION__,", ERROR: ",err_text);

         //---

         m_init_error=true;

         return(INIT_SUCCEEDED);

        }

     }

//---

   m_trade.SetExpertMagicNumber(InpMagic);

   m_trade.SetMarginMode();

   m_trade.SetTypeFillingBySymbol(Symbol());

   m_trade.SetDeviationInPoints(10);

//---

   return(INIT_SUCCEEDED);

  }

//+------------------------------------------------------------------+

//| Expert deinitialization function                                 |

//+------------------------------------------------------------------+

void OnDeinit(const int reason)

  {

//---

  }

//+------------------------------------------------------------------+

//| Expert tick function                                             |

//+------------------------------------------------------------------+

void OnTick()

  {

   if(m_init_error)

      return;

//---

   ClosePartial();

//---

  }

//+------------------------------------------------------------------+

//| Check the correctness of the position volume                     |

//+------------------------------------------------------------------+

bool CheckVolumeValue(double volume,string &error_description)

  {

//--- minimal allowed volume for trade operations

   double min_volume=m_symbol.LotsMin();

   if(volume<min_volume)

     {

      if(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")

         error_description=StringFormat("1J5< <5=LH5 <8=8<0;L=> 4>?CAB8<>3> SYMBOL_VOLUME_MIN=%.2f",min_volume);

      else

         error_description=StringFormat("Volume is less than the minimal allowed SYMBOL_VOLUME_MIN=%.2f",min_volume);

      return(false);

     }

//--- maximal allowed volume of trade operations

   double max_volume=m_symbol.LotsMax();

   if(volume>max_volume)

     {

      if(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")

         error_description=StringFormat("1J5< 1>;LH5 <0:A8<0;L=> 4>?CAB8<>3> SYMBOL_VOLUME_MAX=%.2f",max_volume);

      else

         error_description=StringFormat("Volume is greater than the maximal allowed SYMBOL_VOLUME_MAX=%.2f",max_volume);

      return(false);

     }

//--- get minimal step of volume changing

   double volume_step=m_symbol.LotsStep();

   int ratio=(int)MathRound(volume/volume_step);

   if(MathAbs(ratio*volume_step-volume)>0.0000001)

     {

      if(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")

         error_description=StringFormat("1J5< =5 :@0B5= <8=8<0;L=><C H03C SYMBOL_VOLUME_STEP=%.2f, 1;8609H89 ?@028;L=K9 >1J5< %.2f",

                                        volume_step,ratio*volume_step);

      else

         error_description=StringFormat("Volume is not a multiple of the minimal step SYMBOL_VOLUME_STEP=%.2f, the closest correct volume is %.2f",

                                        volume_step,ratio*volume_step);

      return(false);

     }

   error_description="Correct volume value";

//---

   return(true);

  }

//+------------------------------------------------------------------+

//| Lot Check                                                        |

//+------------------------------------------------------------------+

double LotCheck(double lots,CSymbolInfo &symbol)

  {

//--- calculate maximum volume

   double volume=NormalizeDouble(lots,2);

   double stepvol=symbol.LotsStep();

   if(stepvol>0.0)

      volume=stepvol*MathFloor(volume/stepvol);

//---

   double minvol=symbol.LotsMin();

   if(volume<minvol)

      volume=0.0;

//---

   double maxvol=symbol.LotsMax();

   if(volume>maxvol)

      volume=maxvol;

//---

   return(volume);

  }

//+------------------------------------------------------------------+

//| Close Partial                                                    |

//+------------------------------------------------------------------+

void ClosePartial()

  {

   MqlTick ticks[];

   ArraySetAsSeries(ticks,true);

   int start_pos=0,count=5;

   if(CopyTicks(Symbol(),ticks,COPY_TICKS_ALL,0,count)!=count)

      return;

   double ask_max=DBL_MIN,ask_min=DBL_MAX,bid_max=DBL_MIN,bid_min=DBL_MAX;

   for(int i=0; i<count; i++)

     {

      if(ticks[i].ask>ask_max)

         ask_max=ticks[i].ask;

      if(ticks[i].ask<ask_min)

         ask_min=ticks[i].ask;

      if(ticks[i].bid>bid_max)

         bid_max=ticks[i].bid;

      if(ticks[i].bid<bid_min)

         bid_min=ticks[i].bid;

     }

   if(ask_max==DBL_MIN || ask_min==DBL_MAX || bid_max==DBL_MIN || bid_min==DBL_MAX)

      return;

//---

   long obj_type=ObjectGetInteger(ChartID(),InpHLineName,OBJPROP_TYPE,0);

   if(obj_type!=OBJ_HLINE)

      return;

   double line_price=ObjectGetDouble(ChartID(),InpHLineName,OBJPROP_PRICE,0);

   if(line_price==0.0)

      return;

//---

   int size=ArraySize(m_array_identifier);

   bool find=false;

   for(int j=size-1; j>=0; j--)

     {

      find=false;

      for(int i=PositionsTotal()-1; i>=0; i--) // returns the number of open positions

         if(m_position.SelectByIndex(i))

            if(m_position.Symbol()==Symbol())

              {

               long identifier = m_position.Identifier();

               if(identifier==m_array_identifier[j])

                 {

                  find=true;

                  break;

                 }

              }

      //---

      if(!find)

        {

         ArrayRemove(m_array_identifier,j,1);

         size=ArraySize(m_array_identifier);

        }

     }

//---

   for(int i=PositionsTotal()-1; i>=0; i--) // returns the number of open positions

      if(m_position.SelectByIndex(i))

         if(m_position.Symbol()==Symbol())

           {

            long identifier = m_position.Identifier();

            size=ArraySize(m_array_identifier);

            find=false;

            for(int j=0; j<size; j++)

               if(identifier==m_array_identifier[j])

                 {

                  find=true;

                  break;

                 }

            if(find)

               continue;

            //---

            double lot=0.0;

            if(InpFixing==percent)

              {

               lot=LotCheck(m_position.Volume()*InpVolumeFixing/100.0,m_symbol);

               if(lot==0.0)

                  m_trade.PositionClose(m_position.Ticket(),-1);

              }

            else

              {

               lot=InpVolumeFixing;

              }

            //---

            if(m_position.PositionType()==POSITION_TYPE_BUY)

               if(bid_min<line_price && line_price<bid_max)

                 {

                  if(m_trade.PositionClosePartial(m_position.Ticket(),lot,-1))

                    {

                     size=ArraySize(m_array_identifier);

                     ArrayResize(m_array_identifier,size+1);

                     m_array_identifier[size]=identifier;

                     continue;

                    }

                 }

            //---

            if(m_position.PositionType()==POSITION_TYPE_SELL)

               if(ask_min<line_price && line_price<ask_max)

                  if(m_trade.PositionClosePartial(m_position.Ticket(),lot,-1))

                    {

                     size=ArraySize(m_array_identifier);

                     ArrayResize(m_array_identifier,size+1);

                     m_array_identifier[size]=identifier;

                     continue;

                    }

           }

  }

//+------------------------------------------------------------------+

Comments

Markdown supported. Formatting help

Markdown Formatting Guide

Element Markdown Syntax
Heading # H1
## H2
### H3
Bold **bold text**
Italic *italicized text*
Link [title](https://www.example.com)
Image ![alt text](image.jpg)
Code `code`
Code Block ```
code block
```
Quote > blockquote
Unordered List - Item 1
- Item 2
Ordered List 1. First item
2. Second item
Horizontal Rule ---