Advertisement
Guest User

ashi

a guest
Jun 6th, 2018
94
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 127.89 KB | None | 0 0
  1. //+------------------------------------------------------------------+
  2. //| ashix EA
  3. //|
  4. //|    Generated by StrategyQuant 3.9.66 for MetaTrader
  5. //|    Generated at 06/19/2018 21:06
  6. //+------------------------------------------------------------------+
  7.  
  8. #property copyright "StrategyQuant.com"
  9. #property link      "http://www.StrategyQuant.com"
  10.  
  11. #include <Expert/Expert.mqh>
  12. #include <Trade/SymbolInfo.mqh>
  13. #include <Trade/OrderInfo.mqh>
  14. #include <Trade/HistoryOrderInfo.mqh>
  15. #include <Trade/PositionInfo.mqh>
  16. #include <Trade/DealInfo.mqh>
  17. #include <Trade/TerminalInfo.mqh>    
  18. #include <Object.mqh>
  19. #include <MovingAverages.mqh>
  20.  
  21. const int SLPTTYPE_RANGE = 0;
  22. const int SLPTTYPE_LEVEL = 1;
  23.  
  24. //+------------------------------------------------------------------+
  25. // -- Variables
  26. //+------------------------------------------------------------------+
  27. int MagicNumber = 12345;
  28.  
  29.  
  30. //+------------------------------------------------------------------+
  31. // -- SQ Variables
  32. // - add word "extern" in front of the variable you want
  33. //   to make configurable
  34. //+------------------------------------------------------------------+
  35. //extern int Expert_ID = 1234;
  36.  
  37. struct Indicator {
  38.    string name;
  39.    int handle;
  40.    int bufferIndex;
  41. };
  42.  
  43. Indicator indys[];
  44.  
  45. struct LastClosedTrade {
  46.    string symbol;
  47.    int magicNumber;
  48.    datetime closeTime;
  49. };
  50.  
  51. LastClosedTrade lastClosedTrades[];
  52.  
  53. MqlTick latest_price;      // To be used for getting recent/latest price quotes
  54. MqlTradeRequest mrequest;  // To be used for sending our trade requests
  55. MqlTradeResult mresult;    // To be used to get our trade results
  56. MqlRates mrate[];          // To be used to store the prices, volumes and spread of each bar
  57. CTerminalInfo terminalInfo;
  58.                        
  59. string sqStrategyName = "ashix";
  60. datetime startTime = TimeCurrent();
  61. datetime lastCheckedTradeTime = startTime;
  62.                        
  63. extern bool sqDisplayInfoPanel = true;
  64. int sqLabelCorner = 1;
  65. int sqOffsetHorizontal = 5;
  66. int sqOffsetVertical = 20;
  67. color sqLabelColor = clrWhite;
  68.  
  69. int magicNumber;
  70. int minBars = 30;
  71. int sqMaxSlippage;
  72. int sqVerboseMode;
  73. int sqMaxRetries = 5;
  74.  
  75. double gPointPow = 0;
  76. double gPointCoef = 0;                  
  77.  
  78. int deviationPoints = 10;
  79. int sqTicket = 1;
  80. datetime lastBarTime;
  81. bool _sqIsBarOpen;
  82.  
  83.  
  84. string valueIdentificationSymbol = "";
  85.  
  86.  
  87. //+------------------------------------------------------------------+
  88. // -- Functions
  89. //+------------------------------------------------------------------+
  90.  
  91. //+------------------------------------------------------------------+
  92. //| Expert initialization function                                   |
  93. //+------------------------------------------------------------------+
  94. int OnInit(){
  95.    VerboseLog("--------------------------------------------------------");
  96.    VerboseLog("Starting the EA");
  97.  
  98.    //initMagicNumber();
  99.    if(!initIndicators()) return(INIT_FAILED);
  100.    
  101.    double realDigits = _Digits;
  102.    if(realDigits > 0 && realDigits != 2 && realDigits != 4) {
  103.       realDigits -= 1;
  104.    }
  105.  
  106.    gPointPow = MathPow(10, realDigits);
  107.    gPointCoef = 1/gPointPow;
  108.  
  109.    //VerboseLog("Broker stop level: ", SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL));
  110.  
  111.    VerboseLog("--------------------------------------------------------");
  112.    
  113.    if(sqDisplayInfoPanel) {
  114.      sqInitInfoPanel();
  115.    }
  116.    
  117.    
  118.    return(INIT_SUCCEEDED);
  119. }
  120.  
  121. //+------------------------------------------------------------------+
  122. //| Expert deinitialization function                                 |
  123. //+------------------------------------------------------------------+
  124. void OnDeinit(const int reason)
  125.   {
  126.  
  127.   sqDeinitInfoPanel();
  128.  
  129.  
  130.   }
  131.  
  132. //+------------------------------------------------------------------+
  133. //| Expert tick function                                             |
  134. //+------------------------------------------------------------------+
  135. void OnTick() {
  136.    //--- Do we have enough bars to work with?
  137.    if(Bars(_Symbol,_Period) < minBars) {   // if total bars is less than minBars
  138.       Alert(StringFormat("NOT ENOUGH DATA: Less Bars than %d", minBars));
  139.       return;
  140.    }
  141.    
  142.    if(!SymbolInfoTick(_Symbol, latest_price)) {
  143.       Alert("Error getting the latest price quote - error:",GetLastError(),"!!");
  144.       return;
  145.    }
  146.  
  147.    //--- Get the details of the latest 2 bars
  148.    if(CopyRates(_Symbol, _Period, 0, 2, mrate) < 2) {
  149.       Alert("Error copying rates/history data - error:", GetLastError(), "!!");
  150.       ResetLastError();
  151.       return;
  152.    }
  153.      
  154.    ZeroMemory(mrequest);      // Initialization of mrequest structure
  155.  
  156.    checkBarOpen();
  157.    updateLastTrades();
  158.    
  159.    sqTextFillOpens();
  160.    if(_sqIsBarOpen) {
  161.       sqTextFillTotals();
  162.    }
  163.    
  164.    sqManagePositions();
  165.    
  166.    ulong _ticket;
  167.  
  168. //------------------------
  169. // Rule: call
  170. //------------------------
  171.    if (sqHeikenAshi("NULL",0, "Open", 1) < sqHeikenAshi("NULL",0, "Close", 1))
  172.    {
  173.       // Action #1
  174.       sqLogToFile("Signalsx.txt", "up");
  175.  
  176.       // Action #2
  177.       sqLogToFile("Signals.txt", "up");
  178.  
  179.   }
  180.  
  181.  
  182. //------------------------
  183. // Rule: down
  184. //------------------------
  185.    if (sqHeikenAshi("NULL",0, "Open", 1) > sqHeikenAshi("NULL",0, "Close", 1))
  186.    {
  187.       // Action #1
  188.       sqLogToFile("Signalsx.txt", "down");
  189.  
  190.       // Action #2
  191.       sqLogToFile("Signals.txt", "down");
  192.  
  193.   }
  194.  
  195.  
  196.  
  197. }
  198.  
  199. //+------------------------------------------------------------------+
  200. //| Trade transaction event                                             |
  201. //+------------------------------------------------------------------+
  202. //+------------------------------------------------------------------+
  203.  
  204. void updateLastTrades(){
  205.     HistorySelect(lastCheckedTradeTime, TimeCurrent());
  206.     lastCheckedTradeTime = TimeCurrent();
  207.    
  208.     for(int i=HistoryDealsTotal() - 1; i>=0; i--) {
  209.         ulong ticket = HistoryDealGetTicket(i);
  210.         string dealSymbol = HistoryDealGetString(ticket, DEAL_SYMBOL);
  211.         int dealMagic = HistoryDealGetInteger(ticket, DEAL_MAGIC);
  212.         datetime dealTime = HistoryDealGetInteger(ticket, DEAL_TIME);
  213.      
  214.         if(HistoryDealGetInteger(ticket, DEAL_ENTRY) != DEAL_ENTRY_OUT) continue;
  215.        
  216.         int lastTradeIndex = getLastTradeIndex(dealSymbol, dealMagic);
  217.         if(lastTradeIndex >= 0){
  218.            lastClosedTrades[lastTradeIndex].closeTime = dealTime;
  219.         }
  220.         else {
  221.            int prevSize = ArraySize(lastClosedTrades);
  222.            ArrayResize(lastClosedTrades, prevSize + 1, 10);
  223.            
  224.            lastClosedTrades[prevSize].symbol = dealSymbol;
  225.            lastClosedTrades[prevSize].magicNumber = dealMagic;
  226.            lastClosedTrades[prevSize].closeTime = dealTime;
  227.         }
  228.     }
  229. }
  230. //+------------------------------------------------------------------+
  231.  
  232. bool sqTradeRecentlyClosed(string symbol, int magicNumber, bool checkThisBar, bool checkThisMinute) {
  233.     string tradeSymbol = correctSymbol(symbol);
  234.     int lastTradeIndex = -1;
  235.    
  236.     if(tradeSymbol == "Any" || magicNumber == 0){
  237.         for(int a=0; a<ArraySize(lastClosedTrades); a++){
  238.             if((tradeSymbol == "Any" || lastClosedTrades[a].symbol == symbol) && (magicNumber == 0 || lastClosedTrades[a].magicNumber == magicNumber)){
  239.                 if(lastTradeIndex < 0 || lastClosedTrades[a].closeTime > lastClosedTrades[lastTradeIndex].closeTime){
  240.                     lastTradeIndex = a;
  241.                 }
  242.             }
  243.         }
  244.     }
  245.     else {
  246.         lastTradeIndex = getLastTradeIndex(tradeSymbol, magicNumber);
  247.     }
  248.    
  249.     if(lastTradeIndex >= 0) {
  250.         if(checkThisBar) {
  251.                     if(lastClosedTrades[lastTradeIndex].closeTime >= getTime(0)) {
  252.                           // order finished this bar
  253.                           return true;
  254.                     }
  255.           }
  256.  
  257.           if(checkThisMinute) {
  258.             string strCurrentTimeMinutes = TimeToString(TimeCurrent(), TIME_DATE | TIME_MINUTES);
  259.                 string strCloseTimeMinutes = TimeToString(lastClosedTrades[lastTradeIndex].closeTime, TIME_DATE | TIME_MINUTES);
  260.  
  261.                     if(strCurrentTimeMinutes == strCloseTimeMinutes) {
  262.                           // order finished this minute
  263.                           return true;
  264.                     }
  265.           }
  266.     }
  267.    
  268.     return false;
  269. }
  270.    
  271. //+------------------------------------------------------------------+
  272.  
  273. int getLastTradeIndex(string symbol, int magicNumber){
  274.     for(int a=0; a<ArraySize(lastClosedTrades); a++){
  275.         if(lastClosedTrades[a].symbol == symbol && lastClosedTrades[a].magicNumber == magicNumber) return a;
  276.     }
  277.    
  278.     return -1;
  279. }
  280.    
  281. //+------------------------------------------------------------------+
  282.  
  283. bool initIndicators(){
  284.    
  285.    
  286.    for(int a=0; a<ArraySize(indys); a++){
  287.       //--- if the handle is not created
  288.       if(indys[a].handle == INVALID_HANDLE) {
  289.          //--- tell about the failure and output the error code
  290.          Print("Failed to create handle of the indicator, error code %d", GetLastError());
  291.          //--- the indicator is stopped early
  292.          return(false);
  293.       }
  294.    }
  295.    
  296.    return(true);
  297. }
  298.  
  299. //+------------------------------------------------------------------+
  300.  
  301. double sqGetGlobalSL(string symbol, int orderType, double price) {
  302.    return(sqGetSLLevel(symbol, orderType, price, true, 0));
  303. }
  304.  
  305. //+------------------------------------------------------------------+
  306.  
  307. double sqGetGlobalPT(string symbol, int orderType, double price) {
  308.    return(sqGetPTLevel(symbol, orderType, price, true, 0));
  309. }
  310.  
  311. //+------------------------------------------------------------------+
  312.  
  313. double sqGetValueByIdentification(int idHash) {
  314.    string symbol = valueIdentificationSymbol;
  315.  
  316.    return(0);
  317. }
  318.  
  319. //+------------------------------------------------------------------+
  320.    
  321. void sqManagePositions() {
  322.    for (int cc = PositionsTotal() - 1; cc >= 0; cc--) {
  323.       ulong positionTicket = PositionGetTicket(cc);
  324.    
  325.       if (PositionSelectByTicket(positionTicket)) {
  326.  
  327.             sqManageSL2BE(positionTicket);
  328.             sqManageTrailingStop(positionTicket);
  329.             sqManageExitAfterXBars(positionTicket);      }
  330.      
  331.       if(PositionsTotal() <= 0) return;
  332.    }
  333.    
  334.    if(_sqIsBarOpen) {
  335.       sqManageOrderExpirations();
  336.    }
  337. }                                                                                    
  338.  
  339. //+------------------------------------------------------------------+
  340.  
  341. /*
  342. void initMagicNumber(){
  343.     int Period_ID = 0;
  344.     switch ( Period() )
  345.     {
  346.         case PERIOD_MN1: Period_ID = 9; break;
  347.         case PERIOD_W1:  Period_ID = 8; break;
  348.         case PERIOD_D1:  Period_ID = 7; break;
  349.         case PERIOD_H4:  Period_ID = 6; break;
  350.         case PERIOD_H1:  Period_ID = 5; break;
  351.         case PERIOD_M30: Period_ID = 4; break;
  352.         case PERIOD_M15: Period_ID = 3; break;
  353.         case PERIOD_M5:  Period_ID = 2; break;
  354.         case PERIOD_M1:  Period_ID = 1; break;
  355.     }
  356.     magicNumber = MagicNumber * 10 + Period_ID;//Expert_ID * 10 + Period_ID;
  357. }
  358. */
  359.  
  360. //+------------------------------------------------------------------+
  361.  
  362. void checkBarOpen(){
  363.    datetime currentBarTime = mrate[0].time;
  364.    
  365.    _sqIsBarOpen = currentBarTime == 0 || currentBarTime != lastBarTime;
  366.    lastBarTime = currentBarTime;
  367. }
  368.  
  369. //+------------------------------------------------------------------+
  370.  
  371. bool indyCrossesAbove(string indy1, string indy2, int shift1, int shift2) {
  372.    double buffer1[], buffer2[];
  373.    if(!loadIndicatorValues(buffer1, indy1, 2, shift1) || !loadIndicatorValues(buffer2, indy2, 2, shift2)) return false;
  374.    
  375.    return buffer1[0] <= buffer2[0] && buffer1[1] > buffer2[1];
  376. }
  377.  
  378. //+------------------------------------------------------------------+
  379.  
  380. bool indyCrossesBelow(string indy1, string indy2, int shift1, int shift2) {
  381.    double buffer1[], buffer2[];
  382.    if(!loadIndicatorValues(buffer1, indy1, 2, shift1) || !loadIndicatorValues(buffer2, indy2, 2, shift2)) return false;
  383.    
  384.    return buffer1[0] >= buffer2[0] && buffer1[1] < buffer2[1];
  385. }
  386.  
  387. //+------------------------------------------------------------------+
  388.  
  389. bool crossesAbove(string indy, int shift, double value) {
  390.    double buffer[];
  391.    if(!loadIndicatorValues(buffer, indy, 2, shift)) return false;
  392.    
  393.    return buffer[0] <= value && buffer[1] > value;
  394. }
  395.  
  396. //+------------------------------------------------------------------+
  397.  
  398. bool crossesBelow(string indy, int shift, double value) {
  399.    double buffer[];
  400.    if(!loadIndicatorValues(buffer, indy, 2, shift)) return false;
  401.    
  402.    return buffer[0] >= value && buffer[1] < value;
  403. }  
  404.  
  405. //+------------------------------------------------------------------+
  406.  
  407. bool crossesUp(string indy, int shift, double value) {
  408.    double buffer[];
  409.    if(!loadIndicatorValues(buffer, indy, 2, shift)) return false;
  410.    
  411.    return buffer[0] < value && buffer[1] > value;
  412. }
  413.  
  414. //+------------------------------------------------------------------+
  415.  
  416. bool crossesDown(string indy, int shift, double value) {
  417.    double buffer[];
  418.    if(!loadIndicatorValues(buffer, indy, 2, shift)) return false;
  419.    
  420.    return buffer[0] > value && buffer[1] < value;
  421. }
  422.  
  423. //+------------------------------------------------------------------+
  424.  
  425. bool changesUp(string indy, int shift){
  426.    double buffer[];
  427.    if(!loadIndicatorValues(buffer, indy, 3, shift)) return false;
  428.    
  429.    return buffer[0] > buffer[1] && buffer[1] < buffer[2];
  430. }
  431.  
  432. //+------------------------------------------------------------------+
  433.  
  434. bool changesDown(string indy, int shift){
  435.    double buffer[];
  436.    if(!loadIndicatorValues(buffer, indy, 3, shift)) return false;
  437.    
  438.    return buffer[0] < buffer[1] && buffer[1] > buffer[2];
  439. }
  440.  
  441. //+------------------------------------------------------------------+
  442.  
  443. bool sqIsFalling(string indy, int bars, bool allowSameValues, int shift){
  444.    double buffer[];
  445.    bool atLeastOnce = false;
  446.    
  447.    if(!loadIndicatorValues(buffer, indy, bars, shift)) return false;
  448.    
  449.    double lastValue = buffer[0];
  450.    
  451.    for(int a=1; a<bars; a++){
  452.       if(buffer[a] > lastValue || (!allowSameValues && buffer[a] == lastValue)) return false;
  453.      
  454.       if(buffer[a] < lastValue){
  455.          atLeastOnce = true;
  456.       }
  457.      
  458.       lastValue = buffer[a];
  459.    }
  460.    
  461.    return atLeastOnce;
  462. }
  463.  
  464. //+------------------------------------------------------------------+
  465.  
  466. bool sqIsRising(string indy, int bars, bool allowSameValues, int shift){
  467.    double buffer[];
  468.    bool atLeastOnce = false;
  469.    
  470.    if(!loadIndicatorValues(buffer, indy, bars, shift)) return false;
  471.    
  472.    double lastValue = buffer[0];
  473.    
  474.    for(int a=1; a<bars; a++){
  475.       if(buffer[a] < lastValue || (!allowSameValues && buffer[a] == lastValue)) return false;
  476.      
  477.       if(buffer[a] > lastValue){
  478.          atLeastOnce = true;
  479.       }
  480.      
  481.       lastValue = buffer[a];
  482.    }
  483.    
  484.    return atLeastOnce;
  485. }
  486.  
  487. //+------------------------------------------------------------------+
  488.  
  489. double sqGetIndicatorValue(string indicatorIdentification, int shift) {
  490.    double buffer[];
  491.    if(!loadIndicatorValues(buffer, indicatorIdentification, 1, shift)) return 0;
  492.    
  493.    return buffer[0];
  494. }
  495.  
  496. //+------------------------------------------------------------------+
  497.  
  498. double sqGetIndicatorValue(string indicatorIdentification, int bufferIndex, int shift) {
  499.    double buffer[];
  500.    
  501.    ResetLastError();
  502.    
  503.    int index = getIndicatorIndex(indicatorIdentification);
  504.    if(index >= 0) {
  505.    
  506.       waitForData(indys[index].handle, bufferIndex, shift);
  507.    
  508.       if(CopyBuffer(indys[index].handle, bufferIndex, shift, 1, buffer) < 0) {
  509.          int lastError = GetLastError();
  510.          
  511.          PrintFormat("Failed to copy data from the indicator, error code %d", lastError);
  512.          PrintFormat("Error Description: " + ErrorDescription(lastError));
  513.          
  514.          return(0);
  515.       }
  516.      
  517.       return buffer[0];
  518.    }
  519.    else {
  520.       PrintFormat("Failed to copy data from the indicator. Indicator '" + indicatorIdentification + "' was not found.");
  521.       return 0;
  522.    }
  523. }
  524.  
  525. //+------------------------------------------------------------------+
  526.  
  527. double sqGetIndicatorValue(int handle, int bufferIndex, int shift) {
  528.    double buffer[];
  529.    
  530.    ResetLastError();
  531.    
  532.    waitForData(handle, bufferIndex, shift);
  533.  
  534.    if(CopyBuffer(handle, bufferIndex, shift, 1, buffer) < 0) {
  535.       int lastError = GetLastError();
  536.      
  537.       PrintFormat("Failed to copy data from the indicator, error code %d", lastError);
  538.       PrintFormat("Error Description: " + ErrorDescription(lastError));
  539.      
  540.       return(0);
  541.    }
  542.    
  543.    return buffer[0];
  544. }
  545.  
  546. //+------------------------------------------------------------------+
  547.  
  548. /* Waits until indicator data become available */
  549. void waitForData(int handle, int bufferIndex, int shift){
  550.    double buffer[];
  551.    int i, copied = CopyBuffer(handle, bufferIndex, shift, 1, buffer);
  552.    
  553.    if(copied <= 0){
  554.       Sleep(10);
  555.        
  556.       for(i=0; i<100; i++){
  557.          if(BarsCalculated(handle) > 0) break;
  558.          Sleep(10);
  559.       }
  560.    }
  561. }
  562.  
  563. //+------------------------------------------------------------------+
  564.  
  565. bool loadIndicatorValues(double& buffer[], string indy, int bars, int shift){
  566.    //--- reset error code
  567.    ResetLastError();
  568.    //--- fill a part of the Buffer array with values from the indicator buffer that has 0 index
  569.    int index = getIndicatorIndex(indy);
  570.    if(index >= 0) {
  571.       if(CopyBuffer(indys[index].handle, indys[index].bufferIndex, shift, bars, buffer) < 0) {
  572.          //--- if the copying fails, tell the error code
  573.          PrintFormat("Failed to copy data from the indicator, error code %d", GetLastError());
  574.          //--- quit with zero result - it means that the indicator is considered as not calculated
  575.          return(false);
  576.       }
  577.      
  578.       //--- everything is fine
  579.       return(true);
  580.    }
  581.    else {
  582.       ArrayResize(buffer, bars);
  583.      
  584.       string params[];
  585.       if(!extractParams(indy, params)){
  586.          Print("Unknown indicator '" + indy + "'. Cannot parse params");
  587.          return(false);
  588.       }
  589.      
  590.       if(StringFind(indy, "sqHeikenAshi", 0) == 0){
  591.          for(int a=0; a<bars; a++){
  592.             int curShift = StringToInteger(params[3]) + shift + bars - 1 - a;
  593.             buffer[a] = sqHeikenAshi(params[0], (ENUM_TIMEFRAMES) StringToInteger(params[1]), params[2], curShift);
  594.          }
  595.          return(true);
  596.       }
  597.       else if(StringFind(indy, "sqDaily", 0) == 0){
  598.          for(int a=0; a<bars; a++){
  599.             int curShift = StringToInteger(params[3]) + shift + bars - 1 - a;
  600.             buffer[a] = sqDaily(params[0], StringToInteger(params[1]), params[2], curShift);
  601.          }
  602.          return(true);
  603.       }
  604.       else return(false);
  605.    }
  606. }
  607.  
  608. //+------------------------------------------------------------------+
  609.  
  610. bool extractParams(string wholeString, string &buffer[]){
  611.    int bracketPos = StringFind(wholeString, "(") + 1;
  612.    if(bracketPos < 0) return(false);
  613.    
  614.    string paramsStr = StringSubstr(wholeString, bracketPos, StringLen(wholeString) - bracketPos - 1);
  615.          
  616.    StringSplit(paramsStr, StringGetCharacter(",", 0), buffer);
  617.    
  618.    for(int a=0; a<ArraySize(buffer); a++){
  619.       StringTrimLeft(buffer[a]);
  620.       StringTrimRight(buffer[a]);
  621.    }
  622.    
  623.    return(true);
  624. }
  625.  
  626. //+------------------------------------------------------------------+
  627.  
  628. int getIndicatorIndex(string name){
  629.    for(int a=0; a<ArraySize(indys); a++){
  630.       if(StringCompare(indys[a].name, name, true) == 0){
  631.          return a;
  632.       }
  633.    }
  634.    
  635.    //Print("Error - Indicator '" + name + "' not found.");
  636.    return -1;
  637. }
  638.  
  639. //+------------------------------------------------------------------+
  640.  
  641. string correctSymbol(string symbol){
  642.    return (symbol == NULL || symbol == "NULL" || symbol == "Current") ? Symbol() : symbol;
  643. }
  644.  
  645. //+------------------------------------------------------------------+
  646.  
  647. ulong openPosition(ENUM_ORDER_TYPE type, string symbol, double volume, const double price = 0, const double slPrice = 0, const double ptPrice = 0, const int deviation = 100, const string comment = "", const int magicNo = -1, const datetime expiration = NULL, const bool replaceExisting = true){
  648.    
  649.    // check if pending order exists
  650.    if(sqSelectPendingOrderByType(magicNo, symbol, 0, comment)) {
  651.       if(!replaceExisting) {
  652.          Verbose("Pending Order with these parameters already exists, and replace is not allowed!", " ----------------");
  653.          return(0);
  654.       }
  655.  
  656.       // close pending order
  657.       Verbose("Deleting previous pending order");
  658.       sqDeletePendingOrder(OrderGetInteger(ORDER_TICKET));
  659.    } else {
  660.       Log("No pending orders of that type");
  661.    }
  662.    
  663.    Alert("-----SLPT: ", slPrice, ", ", ptPrice);
  664.    
  665.    ZeroMemory(mrequest);
  666.    
  667.    double curPrice = price > 0 ? price : SymbolInfoDouble(symbol, type == ORDER_TYPE_BUY ? SYMBOL_BID : SYMBOL_ASK);
  668.    
  669.    mrequest.action = (type == ORDER_TYPE_BUY_LIMIT || type == ORDER_TYPE_SELL_LIMIT) ? TRADE_ACTION_PENDING : TRADE_ACTION_DEAL;                                       // immediate order execution
  670.    mrequest.price = NormalizeDouble(curPrice,_Digits);                // latest ask price
  671.    mrequest.sl = NormalizeDouble(slPrice, _Digits); // Stop Loss
  672.    mrequest.tp = NormalizeDouble(ptPrice, _Digits); // Take Profit
  673.    mrequest.symbol = correctSymbol(symbol);                                                  // currency pair
  674.    mrequest.volume = volume;                                                  // number of lots to trade
  675.    mrequest.magic = magicNo > 0 ? magicNo : 1234;                                              // Order Magic Number
  676.    mrequest.type = type;                                                      // Buy Order
  677.    mrequest.type_filling = ORDER_FILLING_FOK;                                 // Order execution type
  678.    mrequest.deviation = deviation;                                            // Deviation from current price
  679.    mrequest.comment = comment;//StringLen(comment) > 0 ? comment : StringFormat("SQ ticket: %d", sqTicket++);
  680.    mrequest.expiration = expiration;
  681.    
  682.    //--- send order
  683.    OrderSend(mrequest,mresult);
  684.    // get the result code
  685.    if(mresult.retcode==10009 || mresult.retcode==10008) //Request is completed or order placed
  686.      {
  687.       Alert("The order has been successfully placed with Ticket#:",mresult.order,"!!");
  688.       return mresult.order;
  689.      }
  690.    else
  691.      {
  692.       Alert("The order request could not be completed. Error no.: ", GetLastError());
  693.       Alert("Error description: " + ErrorDescription(GetLastError()));
  694.       ResetLastError();          
  695.       return 0;
  696.      }
  697. }
  698.  
  699. //+------------------------------------------------------------------+
  700. /*
  701. int sqOpenOrder(int orderType, string symbol, double size, double price, double stopLoss, double profitTarget, int magicNumber, string comment, datetime expirationInTime, bool replaceExisting, color arrowColor) {
  702.  
  703.    if(symbol == "NULL" || symbol == "Current") {
  704.       symbol = Symbol();
  705.    }
  706.  
  707.    // check if live order exists
  708.    if(sqSelectOrder(magicNumber, symbol, sqGetDirectionFromOrderType(orderType), comment)) {
  709.       Verbose("Order with these parameters already exists, cannot open another one!");
  710.       Verbose("----------------------------------");
  711.       return(0);
  712.    }
  713.  
  714.    // check if pending order exists
  715.    if(sqSelectPendingOrderByType(magicNumber, symbol, 0, comment)) {
  716.       if(!replaceExisting) {
  717.          Verbose("Pending Order with these parameters already exists, and replace is not allowed!", " ----------------");
  718.          return(0);
  719.       }
  720.  
  721.       // close pending order
  722.       Verbose("Deleting previous pending order");
  723.       sqDeletePendingOrder(OrderGetInteger(ORDER_TICKET));
  724.    } else {
  725.       Log("Existing order doesnt exist");
  726.    }
  727.  
  728.    int ticket = 0;
  729.    if(sqSupportECNBrokers) {
  730.       ticket = sqOpenOrderImpl(orderType, symbol, size, price, 0, 0, magicNumber, comment, expirationInTime, arrowColor);
  731.    } else {
  732.       ticket = sqOpenOrderImpl(orderType, symbol, size, price, stopLoss, profitTarget, magicNumber, comment, expirationInTime, arrowColor);
  733.    }
  734.  
  735.    if(ticket > 0) {
  736.       if(sqSupportECNBrokers && (stopLoss != 0 || profitTarget != 0)) {
  737.          if(!OrderSelect(ticket)) {
  738.             Verbose("Cannot select order with ticket: ",ticket);
  739.          }
  740.  
  741.          bool result = sqOrderModify(ticket, OrderGetDouble(ORDER_PRICE_OPEN), stopLoss, profitTarget);
  742.          if(!result) {
  743.             Verbose("Cannot set SL / PT for this order, deleting it!");
  744.             OrderDelete(ticket);
  745.          }
  746.       }
  747.     }
  748.  
  749.    // reset global variables for this order
  750.    sqSetOrderExpiration(ticket, 0);
  751.    sqSetExitAfterXBars(ticket, 0);
  752.    sqSetMoveSL2BE(ticket, 0, 0);
  753.    sqSetSL2BEAddPips(ticket, 0);
  754.    sqSetTrailingStop(ticket, 0, 0);
  755.    sqSetTSActivation(ticket, 0);
  756.  
  757.     return(ticket);
  758. }
  759.  
  760. //+------------------------------------------------------------------+
  761.  
  762. int sqOpenOrderImpl(int orderType, string symbol, double size, double price, double stopLoss, double profitTarget, int magicNumber, string comment, datetime expiration, color arrowColor) {
  763.    int ticket = 0;
  764.  
  765.    Verbose("Opening order with MagicNumber: ", magicNumber,", type: ", sqGetOrderTypeAsString(orderType), ", size: ", size, ", price: ", price, ", SL: ", stopLoss, ", PT: ", profitTarget, ", comment: ", comment);
  766.    Verbose("Current Ask: ", SymbolInfoDouble(symbol, SYMBOL_ASK), ", Bid: ", SymbolInfoDouble(symbol, SYMBOL_BID));
  767.  
  768.    if(!sqCheckConnected()) {
  769.       return(-1);
  770.    }
  771.  
  772.    int digits = SymbolInfoInteger(symbol, SYMBOL_DIGITS);
  773.  
  774.    GetLastError(); // clear the global variable.
  775.    int error = 0;
  776.    int retries = 0;
  777.    bool result;
  778.  
  779.    while (true) {
  780.  
  781.       if (IsTradeAllowed()) {
  782.  
  783.          if(orderType == ORDER_TYPE_BUY || orderType == ORDER_TYPE_SELL) {
  784.             // get newest Ask/Bid price for market order
  785.             RefreshRates();
  786.             if(orderType == ORDER_TYPE_BUY) {
  787.                price = sqGetAsk(symbol);
  788.             } else {
  789.                price = sqGetBid(symbol);
  790.             }
  791.          }
  792.  
  793.         if (digits > 0) price = NormalizeDouble(price, digits);
  794.    
  795.          ticket = openPosition((ENUM_ORDER_TYPE) orderType, symbol, size, price, stopLoss, profitTarget, sqMaxSlippage, comment, magicNumber, expiration);
  796.          //ticket = OrderSend(symbol, orderType, size, price, sqMaxSlippage, stopLoss, profitTarget, comment, magicNumber, expiration, arrowColor);
  797.          if(ticket > 0) {
  798.             Verbose("Order placed cuccessfuly,ticket: ", ticket);
  799.             return(ticket);
  800.          }
  801.       }
  802.  
  803.       retries++;
  804.       if(!sqProcessErrors(retries, GetLastError())) {
  805.          return(-1);
  806.       }
  807.    }
  808.  
  809.    Verbose("Retries of opening order finished", " ----------------");
  810.    return(-1);
  811. }
  812. */
  813. //+------------------------------------------------------------------+
  814.  
  815. void closeAllPositions(){
  816.    for (int i=PositionsTotal() - 1; i >= 0; i--) {
  817.       ulong ticket = PositionGetTicket(i);
  818.       PositionSelectByTicket(ticket);
  819.      
  820.       if(sqClosePositionAtMarket(ticket)){
  821.          Print(StringFormat("Cannot close position with ticket %d", ticket));
  822.       }
  823.    }
  824. }
  825.  
  826. //+------------------------------------------------------------------+
  827.  
  828. bool closePosition(const ulong ticket, const ulong deviation = 100, const string comment = "", const int magicNo = -1) {
  829.    ZeroMemory(mrequest);
  830.    
  831.    if(!PositionSelectByTicket(ticket)) return(false);
  832.    
  833.    string symbol = PositionGetString(POSITION_SYMBOL);
  834.  
  835.    if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) {
  836.       //--- prepare request for close BUY position
  837.       mrequest.type = ORDER_TYPE_SELL;
  838.       mrequest.price = NormalizeDouble(latest_price.bid, _Digits);
  839.    }
  840.    else {
  841.       //--- prepare request for close SELL position
  842.       mrequest.type = ORDER_TYPE_BUY;
  843.       mrequest.price = NormalizeDouble(latest_price.ask, _Digits);
  844.    }
  845.    //--- setting request
  846.    mrequest.action   = TRADE_ACTION_DEAL;
  847.    mrequest.position = ticket;
  848.    mrequest.symbol   = symbol;
  849.    mrequest.volume   = PositionGetDouble(POSITION_VOLUME);
  850.    mrequest.magic    = magicNo > 0 ? magicNo : magicNumber;
  851.    mrequest.deviation = deviation;
  852.    mrequest.comment = StringLen(comment) > 0 ? comment : PositionGetString(POSITION_COMMENT);
  853.    //--- close position
  854.    OrderSend(mrequest, mresult);
  855.    
  856.    // get the result code
  857.    if(mresult.retcode==10009 || mresult.retcode==10008) //Request is completed or order placed
  858.      {
  859.       Alert("A Buy order has been successfully placed with Ticket#:",mresult.order,"!!");
  860.       return true;
  861.      }
  862.    else
  863.      {
  864.       Alert("The Buy order request could not be completed -error:",GetLastError());
  865.       ResetLastError();          
  866.       return false;
  867.      }
  868.      
  869. }
  870.  
  871. //+------------------------------------------------------------------+
  872.  
  873. bool OrderModify(int ticket, double stopLoss, double profitTarget){
  874.    ZeroMemory(mrequest);
  875.    
  876.    PositionSelectByTicket(ticket);
  877.    
  878.    //--- setting request
  879.    mrequest.action = TRADE_ACTION_SLTP;
  880.    mrequest.symbol = PositionGetString(POSITION_SYMBOL);
  881.    mrequest.magic = PositionGetInteger(POSITION_MAGIC);
  882.    mrequest.position = ticket;
  883.    mrequest.sl = stopLoss != 0 ? stopLoss : PositionGetDouble(POSITION_SL);
  884.    mrequest.tp = profitTarget != 0 ? profitTarget : PositionGetDouble(POSITION_TP);
  885.    
  886.    //--- action and return the result
  887.    return(OrderSend(mrequest,mresult));
  888. }
  889.  
  890. //+------------------------------------------------------------------+
  891. /*
  892. bool sqOrderModifySL(int ticket,double stopLoss, int type) {
  893.    if(!OrderSelect(ticket)) {
  894.       Verbose("Cannot select order with ticket: ",ticket);
  895.    }
  896.    
  897.    double orderOpenPrice = OrderGetDouble(ORDER_PRICE_OPEN);
  898.  
  899.    if(type == SLPTTYPE_RANGE) {
  900.       // convert range to price level
  901.       if(sqGetDirectionFromOrderType(OrderGetInteger(ORDER_TYPE)) == 1) {
  902.          // it is long order
  903.          stopLoss = orderOpenPrice - stopLoss;
  904.       } else {
  905.          stopLoss = orderOpenPrice + stopLoss;
  906.       }
  907.    }
  908.  
  909.    return(sqOrderModify(ticket, orderOpenPrice, stopLoss, OrderGetDouble(ORDER_TP)));
  910. }
  911.  
  912. //+------------------------------------------------------------------+
  913.  
  914. bool sqOrderModifyPT(int ticket,double profitTarget, int type) {
  915.    if(!OrderSelect(ticket)) {
  916.       Verbose("Cannot select order with ticket: ",ticket);
  917.    }
  918.    
  919.    ENUM_ORDER_TYPE orderType = OrderGetInteger(ORDER_TYPE);
  920.    double orderOpenPrice = OrderGetDouble(ORDER_PRICE_OPEN);
  921.    double orderStopLoss = OrderGetDouble(ORDER_SL);
  922.  
  923.    if(type == SLPTTYPE_RANGE) {
  924.       // convert range to price level
  925.       if(sqGetDirectionFromOrderType(orderType) == 1) {
  926.          // it is long order
  927.          profitTarget = orderOpenPrice + profitTarget;
  928.       } else {
  929.          profitTarget = orderOpenPrice - profitTarget;
  930.       }
  931.    }
  932.  
  933.    return(sqOrderModify(ticket, orderOpenPrice, orderStopLoss, profitTarget));
  934. }
  935.  
  936. //+------------------------------------------------------------------+
  937.  
  938. bool sqOrderModify(int ticket, double price, double stopLoss, double profitTarget) {
  939.    if(!OrderSelect(ticket)) {
  940.       Verbose("Cannot select order with ticket: ",ticket);
  941.    }
  942.  
  943.    int digits = SymbolInfoInteger(OrderGetString(ORDER_SYMBOL), SYMBOL_DIGITS);
  944.    if (digits > 0) {
  945.       stopLoss = NormalizeDouble(stopLoss, digits);
  946.       profitTarget = NormalizeDouble(profitTarget, digits);
  947.     }
  948.  
  949.    Verbose("Modifying order with ticket: ", ticket, ", SL: ", stopLoss, " and PT: ", profitTarget);
  950.  
  951.    int orderType = OrderGetInteger(ORDER_TYPE);
  952.  
  953.    if(!sqCheckConnected()) {
  954.       return(false);
  955.    }
  956.  
  957.    GetLastError(); // clear the global variable.
  958.    int error = 0;
  959.    int retries = 0;
  960.    bool result;
  961.  
  962.    while (true) {
  963.  
  964.       if (IsTradeAllowed()) {
  965.          result = OrderModify(ticket, price, stopLoss, profitTarget, OrderGetInteger(ORDER_TIME_EXPIRATION));
  966.          if(result) {
  967.             Verbose("Order modified successfuly");
  968.             return(true);
  969.          }
  970.       }
  971.  
  972.       retries++;
  973.       if(!sqProcessErrors(retries, GetLastError())) {
  974.          return(false);
  975.       }
  976.    }
  977. }
  978. */
  979.  
  980. //+------------------------------------------------------------------+
  981.  
  982. ENUM_ORDER_TYPE_FILLING GetFilling( const string Symb, const uint Type = ORDER_FILLING_FOK ) {
  983.    const ENUM_SYMBOL_TRADE_EXECUTION ExeMode = (ENUM_SYMBOL_TRADE_EXECUTION)::SymbolInfoInteger(Symb, SYMBOL_TRADE_EXEMODE);
  984.    const int FillingMode = (int)::SymbolInfoInteger(Symb, SYMBOL_FILLING_MODE);
  985.    
  986.    if(FillingMode == 0 || (Type >= ORDER_FILLING_RETURN) || ((FillingMode & (Type + 1)) != Type + 1)) {
  987.       if((ExeMode == SYMBOL_TRADE_EXECUTION_EXCHANGE) || (ExeMode == SYMBOL_TRADE_EXECUTION_INSTANT)) {
  988.          return ORDER_FILLING_RETURN;
  989.       }
  990.       else {
  991.          if(FillingMode == SYMBOL_FILLING_IOC) {
  992.             return ORDER_FILLING_IOC;
  993.          }
  994.          else {
  995.             return ORDER_FILLING_FOK;
  996.          }
  997.       }
  998.    }
  999.    else {
  1000.       return Type;
  1001.    }
  1002. }
  1003.  
  1004. //+------------------------------------------------------------------+
  1005.  
  1006. double getDealCurrentProfit(long dealTicket) {
  1007.    long orderTicket = HistoryDealGetInteger(dealTicket, DEAL_ORDER);
  1008.    return getOrderCurrentProfit(orderTicket);
  1009. }
  1010.  
  1011. //+------------------------------------------------------------------+
  1012.  
  1013. double getDealCurrentPriceDifference(long dealTicket){
  1014.    long orderTicket = HistoryDealGetInteger(dealTicket, DEAL_ORDER);
  1015.    return getOrderCurrentPriceDifference(orderTicket);
  1016. }
  1017.  
  1018. //+------------------------------------------------------------------+
  1019.  
  1020. double getOrderCurrentProfit(long orderTicket){
  1021.    if(!OrderSelect(orderTicket)) return(0);
  1022.    
  1023.    ENUM_ORDER_TYPE orderType = OrderGetInteger(ORDER_TYPE);
  1024.    string orderSymbol = OrderGetString(ORDER_SYMBOL);
  1025.    double orderVolume = OrderGetDouble(ORDER_VOLUME_INITIAL);
  1026.    double orderOpenPrice = OrderGetDouble(ORDER_PRICE_OPEN);
  1027.    double orderCurrentPrice = OrderGetDouble(ORDER_PRICE_CURRENT);
  1028.    
  1029.    double profit = 0;
  1030.    
  1031.    OrderCalcProfit(orderType, orderSymbol, orderVolume, orderOpenPrice, orderCurrentPrice, profit);
  1032.    
  1033.    return profit;
  1034. }
  1035.  
  1036. //+------------------------------------------------------------------+
  1037.  
  1038. double getOrderCurrentPriceDifference(long orderTicket){
  1039.    if(!OrderSelect(orderTicket)) return(0);
  1040.    
  1041.    ENUM_ORDER_TYPE orderType = OrderGetInteger(ORDER_TYPE);
  1042.    double orderOpenPrice = OrderGetDouble(ORDER_PRICE_OPEN);
  1043.    double orderCurrentPrice = OrderGetDouble(ORDER_PRICE_CURRENT);
  1044.    
  1045.    return orderType == ORDER_TYPE_BUY ? orderCurrentPrice - orderOpenPrice : orderOpenPrice - orderCurrentPrice;
  1046. }
  1047.  
  1048. //+------------------------------------------------------------------+
  1049. //| old SQ.mqh functions                                                 |
  1050. //+------------------------------------------------------------------+
  1051.  
  1052. double iOpen(string symbol,int tf,int index){
  1053.    if(index < 0) return(-1);
  1054.    double Arr[];
  1055.    ENUM_TIMEFRAMES timeframe=TFMigrate(tf);
  1056.    if(CopyOpen(correctSymbol(symbol),timeframe, index, 1, Arr)>0)
  1057.         return(Arr[0]);
  1058.    else return(-1);
  1059. }
  1060.  
  1061. //+------------------------------------------------------------------+
  1062.  
  1063. double iHigh(string symbol,int tf,int index){
  1064.    if(index < 0) return(-1);
  1065.    double Arr[];
  1066.    ENUM_TIMEFRAMES timeframe=TFMigrate(tf);
  1067.    if(CopyHigh(correctSymbol(symbol),timeframe, index, 1, Arr)>0)
  1068.         return(Arr[0]);
  1069.    else return(-1);
  1070. }
  1071.  
  1072. //+------------------------------------------------------------------+
  1073.  
  1074. double iLow(string symbol,int tf,int index)
  1075. {
  1076.    if(index < 0) return(-1);
  1077.    double Arr[];
  1078.    ENUM_TIMEFRAMES timeframe=TFMigrate(tf);
  1079.    if(CopyLow(correctSymbol(symbol),timeframe, index, 1, Arr)>0)
  1080.         return(Arr[0]);
  1081.    else return(-1);
  1082. }
  1083.  
  1084. //+------------------------------------------------------------------+
  1085.  
  1086. double iClose(string symbol,int tf,int index){
  1087.    if(index < 0) return(-1);
  1088.    double Arr[];
  1089.    ENUM_TIMEFRAMES timeframe=TFMigrate(tf);
  1090.    if(CopyClose(correctSymbol(symbol),timeframe, index, 1, Arr)>0)
  1091.         return(Arr[0]);
  1092.    else return(-1);
  1093. }
  1094.  
  1095. //+------------------------------------------------------------------+
  1096.  
  1097. datetime iTime(string symbol,int tf,int index)
  1098. {
  1099.    if(index < 0) return(-1);
  1100.    ENUM_TIMEFRAMES timeframe=TFMigrate(tf);
  1101.    datetime Arr[];
  1102.    if(CopyTime(correctSymbol(symbol), timeframe, index, 1, Arr)>0)
  1103.         return(Arr[0]);
  1104.    else return(-1);
  1105. }
  1106.  
  1107. //+------------------------------------------------------------------+
  1108.  
  1109. double getOpen(int shift){
  1110.    return iOpen(_Symbol, _Period, shift);
  1111. }
  1112.  
  1113. //+------------------------------------------------------------------+
  1114.  
  1115. double getHigh(int shift){
  1116.    return iHigh(_Symbol, _Period, shift);
  1117. }
  1118.  
  1119. //+------------------------------------------------------------------+
  1120.  
  1121. double getLow(int shift){
  1122.    return iLow(_Symbol, _Period, shift);
  1123. }
  1124.  
  1125. //+------------------------------------------------------------------+
  1126.  
  1127. double getClose(int shift){
  1128.    return iClose(_Symbol, _Period, shift);
  1129. }
  1130.  
  1131. //+------------------------------------------------------------------+
  1132.  
  1133. double getTime(int shift){
  1134.    return iTime(_Symbol, _Period, shift);
  1135. }
  1136.  
  1137. //+------------------------------------------------------------------+
  1138.  
  1139. int TimeHour(datetime date)
  1140. {
  1141.    MqlDateTime tm;
  1142.    TimeToStruct(date,tm);
  1143.    return(tm.hour);
  1144. }
  1145.  
  1146. //+------------------------------------------------------------------+
  1147.  
  1148. int TimeMinute(datetime date)
  1149. {
  1150.    MqlDateTime tm;
  1151.    TimeToStruct(date,tm);
  1152.    return(tm.min);
  1153. }
  1154.  
  1155. //+------------------------------------------------------------------+
  1156.  
  1157. ENUM_TIMEFRAMES TFMigrate(int tf)
  1158.   {
  1159.    switch(tf)
  1160.      {
  1161.       case 0: return(PERIOD_CURRENT);
  1162.       case 1: return(PERIOD_M1);
  1163.       case 5: return(PERIOD_M5);
  1164.       case 15: return(PERIOD_M15);
  1165.       case 30: return(PERIOD_M30);
  1166.       case 60: return(PERIOD_H1);
  1167.       case 240: return(PERIOD_H4);
  1168.       case 1440: return(PERIOD_D1);
  1169.       case 10080: return(PERIOD_W1);
  1170.       case 43200: return(PERIOD_MN1);
  1171.      
  1172.       case 2: return(PERIOD_M2);
  1173.       case 3: return(PERIOD_M3);
  1174.       case 4: return(PERIOD_M4);      
  1175.       case 6: return(PERIOD_M6);
  1176.       case 10: return(PERIOD_M10);
  1177.       case 12: return(PERIOD_M12);
  1178.       case 16385: return(PERIOD_H1);
  1179.       case 16386: return(PERIOD_H2);
  1180.       case 16387: return(PERIOD_H3);
  1181.       case 16388: return(PERIOD_H4);
  1182.       case 16390: return(PERIOD_H6);
  1183.       case 16392: return(PERIOD_H8);
  1184.       case 16396: return(PERIOD_H12);
  1185.       case 16408: return(PERIOD_D1);
  1186.       case 32769: return(PERIOD_W1);
  1187.       case 49153: return(PERIOD_MN1);      
  1188.       default: return(PERIOD_CURRENT);
  1189.      }
  1190. }
  1191.  
  1192. //+------------------------------------------------------------------+
  1193.  
  1194. void sqCloseWorstPosition(string symbol, int magicNo, int direction, string comment) {
  1195.    double minPL = 100000000;
  1196.    ulong ticket = 0;
  1197.  
  1198.    for(int cc = PositionsTotal() - 1; cc >= 0; cc--) {
  1199.       ulong positionTicket = PositionGetTicket(cc);
  1200.    
  1201.       if(PositionSelect(positionTicket)) {
  1202.          double positionProfit = PositionGetDouble(POSITION_PROFIT);
  1203.          
  1204.          if(positionProfit < minPL) {
  1205.             // found order with worse profit
  1206.             minPL = positionProfit;
  1207.             ticket = positionTicket;
  1208.             Verbose("Worse position found, ticket: ", ticket,", PL: ", minPL);
  1209.          }
  1210.       }
  1211.    }
  1212.  
  1213.    if(ticket > 0) {
  1214.       sqClosePositionAtMarket(ticket);
  1215.    }
  1216. }
  1217.  
  1218. //+------------------------------------------------------------------+
  1219. /*
  1220. void sqManageTrailingStop(int positionTicket) {
  1221.    double tempValue = 0;
  1222.    double tempValue2 = 0;
  1223.    double plValue = 0;
  1224.    double newSL = 0;
  1225.    int error;
  1226.  
  1227.    // Trailing Stop
  1228.    tempValue = sqGetPositionTrailingStop(positionTicket, PositionGetInteger(POSITION_TYPE));
  1229.    if(tempValue > 0) {
  1230.       tempValue2 = sqGetPositionTSActivation(positionTicket);
  1231.    
  1232.       string positionSymbol = PositionGetString(POSITION_SYMBOL);  
  1233.       double positionOpenPrice = PositionGetDouble(POSITION_PRICE_OPEN);
  1234.       double positionStopLoss = PositionGetDouble(POSITION_SL);
  1235.       double positionProfitTarget = PositionGetDouble(POSITION_TP);
  1236.  
  1237.       if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) {
  1238.          plValue = sqGetBid(positionSymbol) - positionOpenPrice;
  1239.          newSL = tempValue;
  1240.  
  1241.          if (plValue >= tempValue2 && (positionStopLoss == 0 || positionStopLoss < newSL) && !sqDoublesAreEqual(positionStopLoss, newSL)) {
  1242.             Verbose("Moving trailing stop for order with ticket: ", positionTicket, " to :", newSL);
  1243.             if(!OrderModify(positionTicket, newSL, positionProfitTarget)) {
  1244.                error = GetLastError();
  1245.                Verbose("Failed, error: ", error, " - ", ErrorDescription(error));
  1246.             }
  1247.          }
  1248.       } else { // POSITION_TYPE_SELL
  1249.          plValue = positionOpenPrice - sqGetAsk(positionSymbol);
  1250.          newSL = tempValue;
  1251.  
  1252.          if (plValue >= tempValue2 && (positionStopLoss == 0 || positionStopLoss > newSL) && !sqDoublesAreEqual(positionStopLoss, newSL)) {
  1253.             Verbose("Moving trailing stop for order with ticket: ", positionTicket, " to :", newSL);
  1254.             if(!OrderModify(positionTicket, newSL, positionProfitTarget)) {
  1255.                error = GetLastError();
  1256.                Verbose("Failed, error: ", error, " - ", ErrorDescription(error),", Ask: ", sqGetAsk(positionSymbol), ", Bid: ", sqGetBid(positionSymbol), " Current SL: ",  positionStopLoss);
  1257.             }
  1258.          }
  1259.       }
  1260.    }
  1261. }
  1262. */
  1263.  
  1264. //+------------------------------------------------------------------+
  1265.  
  1266. void sqManageExitAfterXBars(ulong positionTicket) {
  1267.    int exitBars = sqGetExitAfterXBars(positionTicket);
  1268.    
  1269.    if(exitBars > 0) {
  1270.       datetime openTime = PositionGetInteger(POSITION_TIME);
  1271.      
  1272.       if(sqGetOpenBarsForOrder(exitBars+10, openTime) >= exitBars) {
  1273.          Verbose("Exit After ", exitBars, "bars - closing order with ticket: ", positionTicket);
  1274.          sqClosePositionAtMarket(positionTicket);
  1275.       }
  1276.    }
  1277. }
  1278.  
  1279. //+------------------------------------------------------------------+
  1280.  
  1281. /*
  1282. void sqManageSL2BE(ulong positionTicket) {
  1283.    double tempValue = 0;
  1284.    double tempValue2 = 0;
  1285.    double newSL = 0;
  1286.    int error;
  1287.    
  1288.    int positionType = PositionGetInteger(POSITION_TYPE);
  1289.    string positionSymbol = PositionGetString(POSITION_SYMBOL);  
  1290.    double positionOpenPrice = PositionGetDouble(POSITION_PRICE_OPEN);
  1291.    double positionStopLoss = PositionGetDouble(POSITION_SL);
  1292.    double positionProfitTarget = PositionGetDouble(POSITION_TP);
  1293.  
  1294.    // Move Stop Loss to Break Even
  1295.    tempValue = sqGetOrderBreakEven(positionTicket, positionType);
  1296.    tempValue2 = sqGetBreakEvenAddPips(positionTicket);
  1297.    
  1298.    if(tempValue > 0) {
  1299.       if(positionType == POSITION_TYPE_BUY) {
  1300.          newSL = positionOpenPrice + tempValue2;
  1301.          if (positionOpenPrice <= tempValue && (positionStopLoss == 0 || positionStopLoss < newSL) && !sqDoublesAreEqual(positionStopLoss, newSL)) {
  1302.             Verbose("Moving SL 2 BE for order with ticket: ", positionTicket, " to :", newSL);
  1303.             if(!OrderModify(positionTicket, newSL, positionProfitTarget)) {
  1304.                error = GetLastError();
  1305.                Verbose("Failed, error: ", error, " - ", ErrorDescription(error),", Ask: ", sqGetAsk(positionSymbol), ", Bid: ", sqGetBid(positionSymbol), " Current SL: ",  positionStopLoss);
  1306.             }
  1307.          }
  1308.       } else {
  1309.          newSL = positionOpenPrice - tempValue2;
  1310.          if (positionOpenPrice >= tempValue && (positionStopLoss == 0 || positionStopLoss > newSL) && !sqDoublesAreEqual(positionStopLoss, newSL)) {
  1311.             Verbose("Moving SL 2 BE for order with ticket: ", positionTicket, "  to :", newSL);
  1312.             if(!OrderModify(positionTicket, newSL, positionProfitTarget)) {
  1313.                error = GetLastError();
  1314.                Verbose("Failed, error: ", error, " - ", ErrorDescription(error),", Ask: ", sqGetAsk(positionSymbol), ", Bid: ", sqGetBid(positionSymbol), " Current SL: ",  positionStopLoss);
  1315.             }
  1316.          }
  1317.       }
  1318.    }
  1319. }
  1320. */
  1321.  
  1322. //+------------------------------------------------------------------+
  1323.  
  1324. bool sqClosePositionAtMarket(ulong positionTicket) {
  1325.    Verbose("Closing order with ticket: ", positionTicket);
  1326.  
  1327.    ENUM_POSITION_TYPE positionType = PositionGetInteger(POSITION_TYPE);
  1328.    string positionSymbol = PositionGetString(POSITION_SYMBOL);
  1329.  
  1330.    if(!sqCheckConnected()) {
  1331.       return(-1);
  1332.    }
  1333.  
  1334.    GetLastError(); // clear the global variable.
  1335.    int error = 0;
  1336.    int retries = 0;
  1337.    bool result;
  1338.  
  1339.    while (true) {
  1340.       if (IsTradeAllowed()) {
  1341.          double price;
  1342.  
  1343.          if(positionType == POSITION_TYPE_BUY) {
  1344.             price = sqGetBid(positionSymbol);
  1345.          } else {
  1346.             price = sqGetAsk(positionSymbol);
  1347.          }
  1348.  
  1349.          result = closePosition(positionTicket, sqMaxSlippage);
  1350.          if(result) {
  1351.             Verbose("Order deleted successfuly");
  1352.             return(true);
  1353.          }
  1354.       }
  1355.  
  1356.       if(!sqProcessErrors(retries, GetLastError())) {
  1357.          return(-1);
  1358.       }
  1359.    }
  1360. }
  1361.  
  1362. //+------------------------------------------------------------------+
  1363.  
  1364. bool IsTradeAllowed(){
  1365.    return terminalInfo.IsTradeAllowed();
  1366. }
  1367.  
  1368. //+------------------------------------------------------------------+
  1369.  
  1370. bool sqCheckConnected() {
  1371.    if (!terminalInfo.IsConnected()) {
  1372.       Verbose("Not connected!");
  1373.       return(false);
  1374.    }
  1375.    if (IsStopped()) {
  1376.       Verbose("EA stopped!");
  1377.       return(false);
  1378.    }
  1379.  
  1380.    return(true);
  1381. }
  1382.  
  1383. //+------------------------------------------------------------------+
  1384.  
  1385. double sqGetAsk(string symbol) {
  1386.    symbol = correctSymbol(symbol);
  1387.    return(NormalizeDouble(SymbolInfoDouble(symbol, SYMBOL_ASK), _Digits));
  1388. }
  1389.  
  1390. //+------------------------------------------------------------------+
  1391.  
  1392. double sqGetBid(string symbol) {
  1393.    symbol = correctSymbol(symbol);
  1394.    return(NormalizeDouble(SymbolInfoDouble(symbol, SYMBOL_BID), _Digits));
  1395. }
  1396.  
  1397. //+------------------------------------------------------------------+
  1398.  
  1399. bool sqProcessErrors(int retries, int error) {
  1400.    if (retries > sqMaxRetries) {
  1401.       Verbose("Maximum retries ", sqMaxRetries, " reached. Error: ", error, " : " + ErrorDescription(error));
  1402.       return(false);
  1403.    }
  1404.    
  1405.    if(error == TRADE_RETCODE_PRICE_CHANGED || error == TRADE_RETCODE_REQUOTE) {
  1406.       // continue immediately
  1407.       return(true);
  1408.  
  1409.    } else if(error == TRADE_RETCODE_CONNECTION || error == TRADE_RETCODE_INVALID_PRICE || error == TRADE_RETCODE_TIMEOUT
  1410.          /*error == ERR_OFF_QUOTES || error == ERR_BROKER_BUSY || error == ERR_TRADE_CONTEXT_BUSY*/)
  1411.    {
  1412.       Verbose("Retrying #", retries,", Error: ", error, " : " + ErrorDescription(error));
  1413.       sqSleep();
  1414.       return(true);
  1415.  
  1416.    } else {
  1417.       // too serious error
  1418.       Verbose("Non-retriable error. Error: ", error, " : " + ErrorDescription(error));
  1419.       return(false);
  1420.    }
  1421. }
  1422.  
  1423. //+------------------------------------------------------------------+
  1424.  
  1425. void sqManageOrderExpirations() {
  1426.    int tempValue = 0;
  1427.    int barsOpen = 0;
  1428.    
  1429.    for (int i = OrdersTotal() - 1; i >= 0; i--) {
  1430.       ulong orderTicket = OrderGetTicket(i);
  1431.       if(!OrderSelect(orderTicket)) continue;
  1432.  
  1433.       ENUM_ORDER_TYPE orderType = OrderGetInteger(ORDER_TYPE);
  1434.       datetime openTime = OrderGetInteger(ORDER_TIME_SETUP);
  1435.    
  1436.       // Stop/Limit Order Expiration
  1437.       if(orderType != ORDER_TYPE_BUY && orderType != ORDER_TYPE_SELL) {
  1438.          // handle only pending orders
  1439.          tempValue = sqGetOrderExpiration(orderTicket);
  1440.          if(tempValue > 0) {
  1441.             barsOpen = sqGetOpenBarsForOrder(tempValue + 10, openTime);
  1442.             if(barsOpen >= tempValue) {
  1443.                Verbose("Order with ticket: ", orderTicket, " expired");
  1444.                sqDeletePendingOrder(orderTicket);
  1445.             }
  1446.          }
  1447.       }
  1448.    }
  1449. }
  1450.  
  1451. //----------------------------------------------------------------------------
  1452.  
  1453. double sqIndicatorHighest(int period, int nthValue, string indicatorIdentification) {
  1454.    double indicatorValues[200];
  1455.    int i;
  1456.  
  1457.    for(i=0; i<200; i++) {
  1458.       indicatorValues[i] = -2147483647;
  1459.    }
  1460.  
  1461.    for(i=0; i<period; i++) {
  1462.       indicatorValues[i] = sqGetIndicatorValue(indicatorIdentification, i);
  1463.    }
  1464.  
  1465.    ArraySort(indicatorValues);      //ascending order
  1466.    
  1467.    int index = period - nthValue;
  1468.  
  1469.    if(index < 0 || index >= period) {
  1470.       return(-1);
  1471.    }
  1472.  
  1473.    return(indicatorValues[index]);
  1474. }
  1475.  
  1476. //----------------------------------------------------------------------------
  1477.  
  1478. double sqIndicatorLowest(int period, int nthValue, string indicatorIdentification) {
  1479.    double indicatorValues[200];
  1480.    int i;
  1481.  
  1482.    for(i=0; i<200; i++) {
  1483.       indicatorValues[i] = 2147483647;
  1484.    }
  1485.  
  1486.    for(i=0; i<period; i++) {
  1487.       indicatorValues[i] = sqGetIndicatorValue(indicatorIdentification, i);
  1488.    }
  1489.  
  1490.    ArraySort(indicatorValues);
  1491.  
  1492.    if(nthValue < 0 || nthValue >= period) {
  1493.       return(-1);
  1494.    }
  1495.  
  1496.    return(indicatorValues[nthValue]);
  1497. }
  1498.  
  1499. //----------------------------------------------------------------------------
  1500.  
  1501. double sqIndicatorAverage(int period, int maMethod, string indicatorIdentification) {
  1502.    double indicatorValues[10000];
  1503.  
  1504.    for(int i=0; i<period; i++) {
  1505.       indicatorValues[i] = sqGetIndicatorValue(indicatorIdentification, i);
  1506.    }
  1507.    
  1508.    double maValue = iMAOnArray(indicatorValues, period, period, 0, maMethod, 0);
  1509.  
  1510.    return(maValue);
  1511. }
  1512.  
  1513. double iMAOnArray(double &array[], int total, int period, int ma_shift, int ma_method, int shift) {
  1514.    double buf[],arr[];
  1515.    
  1516.    if(total==0) total=ArraySize(array);
  1517.    if(total>0 && total<=period) return(0);
  1518.    if(shift>total-period-ma_shift) return(0);
  1519.    
  1520.    switch(ma_method)
  1521.      {
  1522.       case MODE_SMA :
  1523.         {
  1524.          total=ArrayCopy(arr,array,0,shift+ma_shift,period);
  1525.          if(ArrayResize(buf,total)<0) return(0);
  1526.          double sum=0;
  1527.          int    i,pos=total-1;
  1528.          for(i=1;i<period;i++,pos--)
  1529.             sum+=arr[pos];
  1530.          while(pos>=0)
  1531.            {
  1532.             sum+=arr[pos];
  1533.             buf[pos]=sum/period;
  1534.             sum-=arr[pos+period-1];
  1535.             pos--;
  1536.            }
  1537.          return(buf[0]);
  1538.         }
  1539.       case MODE_EMA :
  1540.         {
  1541.          if(ArrayResize(buf,total)<0) return(0);
  1542.          double pr=2.0/(period+1);
  1543.          int    pos=total-2;
  1544.          while(pos>=0)
  1545.            {
  1546.             if(pos==total-2) buf[pos+1]=array[pos+1];
  1547.             buf[pos]=array[pos]*pr+buf[pos+1]*(1-pr);
  1548.             pos--;
  1549.            }
  1550.          return(buf[shift+ma_shift]);
  1551.         }
  1552.       case MODE_SMMA :
  1553.         {
  1554.          if(ArrayResize(buf,total)<0) return(0);
  1555.          double sum=0;
  1556.          int    i,k,pos;
  1557.          pos=total-period;
  1558.          while(pos>=0)
  1559.            {
  1560.             if(pos==total-period)
  1561.               {
  1562.                for(i=0,k=pos;i<period;i++,k++)
  1563.                  {
  1564.                   sum+=array[k];
  1565.                   buf[k]=0;
  1566.                  }
  1567.               }
  1568.             else sum=buf[pos+1]*(period-1)+array[pos];
  1569.             buf[pos]=sum/period;
  1570.             pos--;
  1571.            }
  1572.          return(buf[shift+ma_shift]);
  1573.         }
  1574.       case MODE_LWMA :
  1575.         {
  1576.          if(ArrayResize(buf,total)<0) return(0);
  1577.          double sum=0.0,lsum=0.0;
  1578.          double price;
  1579.          int    i,weight=0,pos=total-1;
  1580.          for(i=1;i<=period;i++,pos--)
  1581.            {
  1582.             price=array[pos];
  1583.             sum+=price*i;
  1584.             lsum+=price;
  1585.             weight+=i;
  1586.            }
  1587.          pos++;
  1588.          i=pos+period;
  1589.          while(pos>=0)
  1590.            {
  1591.             buf[pos]=sum/weight;
  1592.             if(pos==0) break;
  1593.             pos--;
  1594.             i--;
  1595.             price=array[pos];
  1596.             sum=sum-lsum+price*period;
  1597.             lsum-=array[i];
  1598.             lsum+=price;
  1599.            }
  1600.          return(buf[shift+ma_shift]);
  1601.         }
  1602.       default: return(0);
  1603.      }
  1604.    return(0);
  1605.   }
  1606.  
  1607. //----------------------------------------------------------------------------
  1608.  
  1609. double sqIndicatorRecent(int barsBack, string indicatorIdentification) {
  1610.    return(sqGetIndicatorValue(indicatorIdentification, barsBack));
  1611. }
  1612.  
  1613. //+------------------------------------------------------------------+
  1614.  
  1615. int sqGetOrderExpiration(int ticket) {
  1616.    return (GlobalVariableGet("sqOrderExpiration_"+ticket));
  1617. }
  1618.  
  1619. //+------------------------------------------------------------------+
  1620.  
  1621. void sqSetOrderExpiration(int ticket, int bars) {
  1622.    GlobalVariableSet("sqOrderExpiration_"+ticket, bars);
  1623. }
  1624.  
  1625. //+------------------------------------------------------------------+
  1626.  
  1627. int sqGetExitAfterXBars(int ticket) {
  1628.    return (GlobalVariableGet("sqExitAfterXBars_"+ticket));
  1629. }
  1630.  
  1631. //+------------------------------------------------------------------+
  1632.  
  1633. void sqSetExitAfterXBars(int ticket, int bars) {
  1634.    GlobalVariableSet("sqExitAfterXBars_"+ticket, bars);
  1635. }
  1636.  
  1637. //+------------------------------------------------------------------+
  1638.  
  1639. int sqGetMoveSL2BE(int ticket) {
  1640.    return (GlobalVariableGet("sqMoveSL2BE_"+ticket));
  1641. }
  1642.  
  1643. //+------------------------------------------------------------------+
  1644.  
  1645. int sqGetMoveSL2BEType(int ticket) {
  1646.    return (GlobalVariableGet("sqMoveSL2BEType_"+ticket));
  1647. }
  1648.  
  1649. //+------------------------------------------------------------------+
  1650.  
  1651. void sqSetMoveSL2BE(int ticket, string value, int type) {
  1652.    GlobalVariableSet("sqMoveSL2BE_"+ticket, sqStringHash(value));
  1653.    GlobalVariableSet("sqMoveSL2BEType_"+ticket, type);
  1654. }
  1655.  
  1656. //+------------------------------------------------------------------+
  1657.  
  1658. int sqGetSL2BEAddPips(int ticket) {
  1659.    return (GlobalVariableGet("sqSL2BEAddPips_"+ticket));
  1660. }
  1661.  
  1662. //+------------------------------------------------------------------+
  1663.  
  1664. void sqSetSL2BEAddPips(int ticket, string value) {
  1665.    GlobalVariableSet("sqSL2BEAddPips_"+ticket, sqStringHash(value));
  1666. }
  1667.  
  1668.  
  1669. //+------------------------------------------------------------------+
  1670.  
  1671. int sqGetTrailingStop(int ticket) {
  1672.    return (GlobalVariableGet("sqTrailingStop"+ticket));
  1673. }
  1674.  
  1675. //+------------------------------------------------------------------+
  1676.  
  1677. int sqGetTrailingStopType(int ticket) {
  1678.    return (GlobalVariableGet("sqTrailingStopType"+ticket));
  1679. }
  1680.  
  1681. //+------------------------------------------------------------------+
  1682.  
  1683. void sqSetTrailingStop(int ticket, string value, int type) {
  1684.    GlobalVariableSet("sqTrailingStop"+ticket, sqStringHash(value));
  1685.    GlobalVariableSet("sqTrailingStopType"+ticket, type);
  1686. }
  1687.  
  1688. //+------------------------------------------------------------------+
  1689.  
  1690. int sqGetTSActivation(int positionTicket) {
  1691.    return (GlobalVariableGet("sqTSActivation"+positionTicket));
  1692. }
  1693.  
  1694. //+------------------------------------------------------------------+
  1695.  
  1696. void sqSetTSActivation(int ticket, string value) {
  1697.    GlobalVariableSet("sqTSActivation"+ticket, sqStringHash(value));
  1698. }
  1699.  
  1700. //+------------------------------------------------------------------+
  1701.  
  1702. int sqStringHash(string str){
  1703.    int i, h = 0, k = 0;
  1704.    for (i=0; i<StringLen(str); i++){
  1705.       k = StringGetCharacter(str, i);
  1706.       h = (h << 5) + h + k;
  1707.    }
  1708.    return(h);
  1709. }
  1710.  
  1711. //+------------------------------------------------------------------+
  1712.  
  1713. void sqClosePosition(double size, int magicNumber, string symbol, int direction, string comment) {
  1714.    Verbose("Closing order with Magic Number: ", magicNumber, ", symbol: ", symbol, ", direction: ", direction, ", comment: ", comment);
  1715.  
  1716.    if(!sqSelectPosition(magicNumber, symbol, direction, comment)) {
  1717.       Verbose("Position cannot be found");
  1718.    } else {
  1719.       ENUM_POSITION_TYPE positionType = PositionGetInteger(POSITION_TYPE);
  1720.       if(positionType == POSITION_TYPE_BUY || positionType == POSITION_TYPE_SELL) {
  1721.          sqClosePositionAtMarket(size);
  1722.       } else {
  1723.          //sqDeletePendingOrder(OrderTicket());
  1724.       }
  1725.    }
  1726.  
  1727.    Verbose("Closing order finished ----------------");
  1728. }
  1729.  
  1730.  
  1731. //+------------------------------------------------------------------+
  1732.  
  1733. int sqGetOpenBarsForOrder(int expBarsPeriod, datetime openTime) {
  1734.    datetime Time[];
  1735.    int length = CopyTime(_Symbol, _Period, 0, expBarsPeriod+10, Time);
  1736.    
  1737.    if(length <= 0) return 0;
  1738.    
  1739.    ArrayGetAsSeries(Time);
  1740.    
  1741.    int numberOfBars = 0;
  1742.    for(int i=0; i<length; i++) {
  1743.       if(openTime < Time[i]) {
  1744.          numberOfBars++;
  1745.       }
  1746.    }
  1747.  
  1748.    return(numberOfBars);
  1749. }
  1750.  
  1751. //+------------------------------------------------------------------+
  1752.  
  1753. void Verbose(string st1, string st2="", string s3="", string s4="", string s5="", string s6="", string s7="", string s8="", string s9="", string s10="", string s11="", string s12="", string s13="", string s14="" ) {
  1754.    if(sqVerboseMode == 1) {
  1755.       // log to standard log
  1756.       Print("---VERBOSE--- ", TimeToString(TimeCurrent()), " ", st1, st2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14);
  1757.  
  1758.    } else if(sqVerboseMode == 2) {
  1759.       // log to special file
  1760.       int handle = FileOpen("EAW_VerboseLog.txt", FILE_READ | FILE_WRITE);
  1761.       if(handle>0) {
  1762.          FileSeek(handle,0,SEEK_END);
  1763.          FileWrite(handle, TimeToString(TimeCurrent()), " VERBOSE: ", st1, st2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12);
  1764.          FileClose(handle);
  1765.       }
  1766.    }
  1767. }
  1768.  
  1769. //+------------------------------------------------------------------+
  1770.  
  1771. void VerboseLog(string s1, string s2="", string s3="", string s4="", string s5="", string s6="", string s7="", string s8="", string s9="", string s10="", string s11="", string s12="" ) {
  1772.    if(sqVerboseMode != 1) {
  1773.       Log(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12);
  1774.    }
  1775.  
  1776.    Verbose(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12);
  1777. }
  1778.  
  1779. //+------------------------------------------------------------------+
  1780.  
  1781. void Log(string s1, string s2="", string s3="", string s4="", string s5="", string s6="", string s7="", string s8="", string s9="", string s10="", string s11="", string s12="" ) {
  1782.    Print(TimeToString(TimeCurrent()), " ", s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12);
  1783. }
  1784.  
  1785. //+------------------------------------------------------------------+
  1786.  
  1787. void sqLog(string st1, string st2="", string s3="", string s4="", string s5="", string s6="", string s7="", string s8="", string s9="", string s10="", string s11="", string s12="" ) {
  1788.    Print(TimeToString(TimeCurrent()), " ", st1, st2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12);
  1789. }
  1790.  
  1791.  
  1792. //+------------------------------------------------------------------+
  1793.  
  1794. void sqLogToFile(string fileName, string st1, string st2="", string s3="", string s4="", string s5="", string s6="", string s7="", string s8="", string s9="", string s10="", string s11="", string s12="" ) {
  1795.    int handle = FileOpen(fileName, FILE_READ | FILE_WRITE, ";");
  1796.    if(handle>0) {
  1797.       FileSeek(handle,0,SEEK_END);
  1798.       FileWrite(handle, TimeToString(TimeCurrent()), " ", st1, st2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12);
  1799.       FileClose(handle);
  1800.    }
  1801. }
  1802.  
  1803. //+------------------------------------------------------------------+
  1804.  
  1805. bool sqSelectPosition(int magicNumber, string symbol, int direction, string comment) {
  1806.    for (int cc = PositionsTotal() - 1; cc >= 0; cc--) {
  1807.       ulong ticket = PositionGetTicket(cc);
  1808.  
  1809.       if (PositionSelectByTicket(ticket) && positionFits(ticket, symbol, magicNumber, direction, comment)) {
  1810.          return(true);
  1811.       }
  1812.    }
  1813.  
  1814.    return(false);
  1815. }
  1816.  
  1817. //+------------------------------------------------------------------+
  1818.  
  1819. bool sqSelectOrder(int magicNumber, string symbol, int direction, string comment) {
  1820.    for (int cc = OrdersTotal() - 1; cc >= 0; cc--) {
  1821.       ulong ticket = OrderGetTicket(cc);
  1822.  
  1823.       if (OrderSelect(ticket) && orderFits(ticket, symbol, magicNumber, direction, comment)) {
  1824.          return(true);
  1825.       }
  1826.    }
  1827.  
  1828.    return(false);
  1829. }
  1830.  
  1831. //+------------------------------------------------------------------+
  1832.  
  1833. bool positionFits(ulong ticket, string symbol, int magicNumber, int direction, string comment){
  1834.    ENUM_POSITION_TYPE positionType = PositionGetInteger(POSITION_TYPE);  
  1835.    string positionSymbol = PositionGetString(POSITION_SYMBOL);        
  1836.    string positionComment = PositionGetString(POSITION_COMMENT);    
  1837.    int positionMagicNumber = PositionGetInteger(POSITION_MAGIC);
  1838.    
  1839.    if(direction != 0) {
  1840.       if(direction > 0 && positionType != POSITION_TYPE_BUY) return(false);
  1841.       if(direction < 0 && positionType != POSITION_TYPE_SELL) return(false);
  1842.    }
  1843.  
  1844.    if(magicNumber != 0) {
  1845.       if(positionMagicNumber != magicNumber) return(false);
  1846.    }
  1847.  
  1848.    if(symbol != "Any") {
  1849.       if(symbol == "NULL" || symbol == "Current") {
  1850.          symbol = Symbol();
  1851.       }
  1852.  
  1853.       if(positionSymbol != symbol) return(false);
  1854.    }
  1855.  
  1856.    if(comment != "") {
  1857.       if(StringFind(positionComment, comment) == -1) return(false);
  1858.    }
  1859.    
  1860.    return(true);
  1861. }
  1862.  
  1863. //+------------------------------------------------------------------+
  1864.  
  1865. bool dealFits(ulong ticket, string symbol, int magicNumber, int direction, string comment){
  1866.    ENUM_DEAL_TYPE dealType = HistoryDealGetInteger(ticket, DEAL_TYPE);
  1867.    string dealSymbol = HistoryDealGetString(ticket, DEAL_SYMBOL);      
  1868.    string dealComment = HistoryDealGetString(ticket, DEAL_COMMENT);  
  1869.    int dealMagicNumber = HistoryDealGetInteger(ticket, DEAL_MAGIC);
  1870.    
  1871.    if(direction != 0) {
  1872.       if(direction > 0 && dealType != DEAL_TYPE_BUY) return(false);
  1873.       if(direction < 0 && dealType != DEAL_TYPE_SELL) return(false);
  1874.    }
  1875.  
  1876.    if(magicNumber != 0) {
  1877.       if(dealMagicNumber != magicNumber) return(false);
  1878.    }
  1879.  
  1880.    if(symbol != "Any") {
  1881.       if(symbol == "NULL" || symbol == "Current") {
  1882.          symbol = Symbol();
  1883.       }
  1884.  
  1885.       if(dealSymbol != symbol) return(false);
  1886.    }
  1887.  
  1888.    if(comment != "") {
  1889.       if(StringFind(dealComment, comment) == -1) return(false);
  1890.    }
  1891.    
  1892.    return(true);
  1893. }
  1894.  
  1895. //+------------------------------------------------------------------+
  1896.  
  1897. bool orderFits(ulong ticket, string symbol, int magicNumber, int direction, string comment){
  1898.    ENUM_ORDER_TYPE orderType = OrderGetInteger(ORDER_TYPE);
  1899.    string orderSymbol = OrderGetString(ORDER_SYMBOL);      
  1900.    string orderComment = OrderGetString(ORDER_COMMENT);  
  1901.    int orderMagicNumber = OrderGetInteger(ORDER_MAGIC);
  1902.    
  1903.    if(direction != 0) {
  1904.       if(direction > 0 && orderType != ORDER_TYPE_BUY) return(false);
  1905.       if(direction < 0 && orderType != ORDER_TYPE_SELL) return(false);
  1906.    }
  1907.  
  1908.    if(magicNumber != 0) {
  1909.       if(orderMagicNumber != magicNumber) return(false);
  1910.    }
  1911.  
  1912.    if(symbol != "Any") {
  1913.       if(symbol == "NULL" || symbol == "Current") {
  1914.          symbol = Symbol();
  1915.       }
  1916.  
  1917.       if(orderSymbol != symbol) return(false);
  1918.    }
  1919.  
  1920.    if(comment != "") {
  1921.       if(StringFind(orderComment, comment) == -1) return(false);
  1922.    }
  1923.    
  1924.    return(true);
  1925. }
  1926.  
  1927. //+------------------------------------------------------------------+
  1928.  
  1929. void sqCloseAllPositions(string symbol, int magicNumber, int direction, string comment) {
  1930.    int count = 100; // maximum number of positions to close
  1931.    ulong lastTicket = -1;
  1932.  
  1933.    while(count > 0) {
  1934.       count--;
  1935.       if(!sqSelectPosition(magicNumber, symbol, direction, comment)) {
  1936.          // no position found
  1937.          break;
  1938.       }
  1939.      
  1940.       ulong positionTicket = PositionGetInteger(POSITION_TICKET);
  1941.      
  1942.       if(lastTicket == positionTicket) {
  1943.          // trying to close the same position one more time, there must be some error
  1944.          break;
  1945.       }
  1946.      
  1947.       lastTicket = positionTicket;
  1948.      
  1949.       sqClosePositionAtMarket(positionTicket);
  1950.    }
  1951. }
  1952.  
  1953. //+------------------------------------------------------------------+
  1954.  
  1955. void sqCloseBestPosition(string symbol, int magicNumber, int direction, string comment) {
  1956.    double maxPL = -100000000;
  1957.    ulong ticket = 0;
  1958.  
  1959.    for (int cc = PositionsTotal() - 1; cc >= 0; cc--) {
  1960.       ulong positionTicket = PositionGetTicket(cc);
  1961.  
  1962.       if(PositionSelectByTicket(positionTicket) && positionFits(positionTicket, symbol, magicNumber, direction, comment)) {
  1963.           double positionProfit = PositionGetDouble(POSITION_PROFIT);
  1964.            
  1965.           if(positionProfit > maxPL) {
  1966.             // found order with better profit
  1967.             maxPL = positionProfit;
  1968.             ticket = positionTicket;
  1969.             Verbose("Better position found, ticket: ", positionTicket,", PL: ", maxPL);
  1970.           }
  1971.       }
  1972.    }
  1973.  
  1974.    if(ticket > 0) {
  1975.       PositionSelectByTicket(ticket);
  1976.       sqClosePositionAtMarket(ticket);
  1977.    }
  1978. }
  1979.  
  1980. //+------------------------------------------------------------------+
  1981.  
  1982. int sqGetMarketPosition(string symbol, int magicNumber, string comment) {
  1983.    if(sqSelectPosition(magicNumber, symbol, 0, comment)) {
  1984.       ENUM_POSITION_TYPE positionType = PositionGetInteger(POSITION_TYPE);
  1985.       if(positionType == POSITION_TYPE_BUY) {
  1986.          return(1);
  1987.       } else {
  1988.          return(-1);
  1989.       }
  1990.    }
  1991.    /*
  1992.    //check pending orders
  1993.    if(sqSelectOrder(magicNumber, symbol, 0, comment)) {
  1994.       ENUM_ORDER_TYPE orderType = OrderGetInteger(ORDER_TYPE);
  1995.      
  1996.       if(orderType != ORDER_TYPE_BUY && orderType != ORDER_TYPE_SELL) {
  1997.          return(-1);
  1998.       }
  1999.    }
  2000.    */
  2001.    return(0);
  2002. }
  2003.  
  2004. //+------------------------------------------------------------------+
  2005.  
  2006. double sqGetPositionOpenPrice(string symbol, int magicNumber, int direction, string comment) {
  2007.    if(sqSelectPosition(magicNumber, symbol, direction, comment)) {
  2008.       return(PositionGetDouble(POSITION_PRICE_OPEN));
  2009.    }
  2010.    return(-1);
  2011. }
  2012.  
  2013. //+------------------------------------------------------------------+
  2014.  
  2015. double sqGetOrderStopLoss(string symbol, int magicNumber, int direction, string comment) {
  2016.    if(sqSelectPosition(magicNumber, symbol, direction, comment)) {
  2017.       return(PositionGetDouble(POSITION_SL));
  2018.    }
  2019.    return(-1);
  2020. }
  2021.  
  2022. //+------------------------------------------------------------------+
  2023.  
  2024. double sqGetOrderProfitTarget(string symbol, int magicNumber, int direction, string comment) {
  2025.    if(sqSelectPosition(magicNumber, symbol, direction, comment)) {
  2026.       return(PositionGetDouble(POSITION_TP));
  2027.    }
  2028.    return(-1);
  2029. }
  2030.  
  2031. //+------------------------------------------------------------------+
  2032.  
  2033. double sqGetMarketPositionSize(string symbol, int magicNumber, int direction, string comment) {
  2034.    double lots = 0;
  2035.  
  2036.    for (int cc = PositionsTotal() - 1; cc >= 0; cc--) {
  2037.       ulong positionTicket = PositionGetTicket(cc);
  2038.  
  2039.       if(PositionSelectByTicket(positionTicket) && positionFits(positionTicket, symbol, magicNumber, direction, comment)) {
  2040.          lots += PositionGetDouble(POSITION_VOLUME);
  2041.       }
  2042.    }
  2043.  
  2044.    return(lots);
  2045. }
  2046.  
  2047. //+------------------------------------------------------------------+
  2048.  
  2049. double sqGetOpenPL(string symbol, int magicNumber, int direction, string comment) {
  2050.    double pl = 0;
  2051.  
  2052.    for (int cc = PositionsTotal() - 1; cc >= 0; cc--) {
  2053.       ulong positionTicket = PositionGetTicket(cc);
  2054.  
  2055.       if(PositionSelectByTicket(positionTicket) && positionFits(positionTicket, symbol, magicNumber, direction, comment)) {
  2056.          pl += PositionGetDouble(POSITION_PROFIT);
  2057.       }
  2058.    }
  2059.  
  2060.    return(pl);
  2061. }
  2062.  
  2063. //+------------------------------------------------------------------+
  2064.  
  2065. double sqGetOpenPLInPips(string symbol, int magicNumber, int direction, string comment) {
  2066.    double priceDelta = 0;
  2067.    
  2068.    for (int cc = PositionsTotal() - 1; cc >= 0; cc--) {
  2069.       ulong positionTicket = PositionGetTicket(cc);
  2070.  
  2071.       if(PositionSelectByTicket(positionTicket) && positionFits(positionTicket, symbol, magicNumber, direction, comment)) {
  2072.          ENUM_POSITION_TYPE positionType = PositionGetInteger(POSITION_TYPE);
  2073.          double positionOpenPrice = PositionGetDouble(POSITION_PRICE_OPEN);
  2074.          double positionCurrentPrice = PositionGetDouble(POSITION_PRICE_CURRENT);
  2075.          
  2076.          if(positionType == POSITION_TYPE_BUY){
  2077.             priceDelta += positionCurrentPrice - positionOpenPrice;
  2078.          }
  2079.          else {
  2080.             priceDelta += positionOpenPrice - positionCurrentPrice;
  2081.          }
  2082.       }
  2083.    }
  2084.    
  2085.    return(sqConvertToPips(symbol, priceDelta));
  2086. }
  2087.  
  2088. //+------------------------------------------------------------------+
  2089. /*
  2090. int sqGetClosedPLInPips(string symbol, int magicNumber, int direction, string comment, int shift) {
  2091.    int index = 0;
  2092.    
  2093.    HistorySelect(startTime, getTime(0));
  2094.    
  2095.    for(int i=HistoryDealsTotal(); i>=0; i--) {
  2096.       ulong ticket = HistoryDealGetTicket(i);
  2097.        
  2098.       if(dealFits(ticket, symbol, magicNumber, direction, comment)) {
  2099.          ENUM_DEAL_TYPE dealType = HistoryDealGetInteger(ticket, DEAL_TYPE);
  2100.          double profit = HistoryDealGetDouble(ticket, DEAL_PROFIT);  
  2101.      
  2102.          if(index == shift) {
  2103.             if(dealType == DEAL_TYPE_BUY) {
  2104.                return(sqConvertToPips(correctSymbol(symbol), OrderClosePrice() - OrderOpenPrice()));
  2105.             } else {
  2106.                return(sqConvertToPips(correctSymbol(symbol), OrderOpenPrice() - OrderClosePrice()));
  2107.             }
  2108.          }
  2109.  
  2110.          index++;
  2111.       }
  2112.    }
  2113.  
  2114.    return(0);
  2115. }
  2116.  
  2117. //+------------------------------------------------------------------+
  2118.  
  2119. double getDealPriceDelta(ulong ticket){
  2120.    double profit = HistoryDealGetDouble(ticket, DEAL_PROFIT);
  2121.    double volume = HistoryDealGetDouble(ticket, DEAL_VOLUME);
  2122.    string dealSymbol = HistoryDealGetString(ticket, DEAL_SYMBOL);
  2123.    
  2124.    double contractSize = SymbolInfoDouble(dealSymbol, SYMBOL_TRADE_CONTRACT_SIZE);
  2125.    double pointValue = SymbolInfoDouble(dealSymbol, SYMBOL_POINT);
  2126.                
  2127.    return profit * pointValue / contractSize;
  2128. }
  2129. */
  2130. //+------------------------------------------------------------------+
  2131.  
  2132. int sqGetClosedPLInMoney(string symbol, int magicNumber, int direction, string comment, int shift) {
  2133.    int index = 0;
  2134.    
  2135.    HistorySelect(startTime, getTime(0));
  2136.  
  2137.    for(int i=HistoryDealsTotal(); i>=0; i--) {
  2138.       ulong ticket = HistoryDealGetTicket(i);
  2139.      
  2140.       if(dealFits(ticket, symbol, magicNumber, direction, comment)) {
  2141.          if(index == shift) {
  2142.             return(HistoryDealGetDouble(ticket, DEAL_PROFIT));
  2143.          }
  2144.  
  2145.          index++;
  2146.       }
  2147.    }
  2148.  
  2149.    return(0);
  2150. }
  2151.  
  2152. //+------------------------------------------------------------------+
  2153.  
  2154. int sqGetMarketPositionCount(string symbol, int magicNumber, int direction, string comment) {
  2155.    double count = 0;
  2156.  
  2157.    for (int cc = PositionsTotal() - 1; cc >= 0; cc--) {
  2158.       ulong positionTicket = PositionGetTicket(cc);
  2159.    
  2160.       if(PositionSelect(positionTicket) && positionFits(positionTicket, symbol, magicNumber, direction, comment)) {
  2161.          count++;
  2162.       }
  2163.    }
  2164.  
  2165.    return(count);
  2166. }
  2167.  
  2168. //+------------------------------------------------------------------+
  2169.  
  2170. int sqGetBarsSinceOpen(string symbol, int magicNumber, int direction, string comment) {
  2171.    if(sqSelectPosition(magicNumber, symbol, direction, comment)) {
  2172.       datetime positionOpenTime = PositionGetInteger(POSITION_TIME);
  2173.       int numberOfBars = 0;
  2174.      
  2175.       datetime Time[];
  2176.       int length = CopyTime(_Symbol, _Period, 0, 10000, Time);
  2177.      
  2178.       if(length <= 0) return 0;
  2179.      
  2180.       ArrayGetAsSeries(Time);
  2181.      
  2182.       for(int i=0; i<10000; i++) {
  2183.          if(positionOpenTime < Time[i]) {
  2184.             numberOfBars++;
  2185.          }
  2186.       }
  2187.  
  2188.       return(numberOfBars);
  2189.    }
  2190.  
  2191.    return(-1);
  2192. }
  2193.  
  2194. //+------------------------------------------------------------------+
  2195.  
  2196. int sqGetBarsSinceClose(string symbol, int magicNumber, int direction, string comment) {
  2197.    ulong ticket = sqSelectDeal(magicNumber, symbol, direction, comment);
  2198.    if(ticket > 0) {
  2199.       datetime clTime = HistoryDealGetInteger(ticket, DEAL_TIME);
  2200.      
  2201.       datetime Time[];
  2202.       int length = CopyTime(_Symbol, _Period, 0, 10000, Time);
  2203.       if(length <= 0) return 0;
  2204.      
  2205.       ArrayGetAsSeries(Time);
  2206.      
  2207.       int numberOfBars = 0;
  2208.       for(int i=0; i<10000; i++) {
  2209.          if(clTime < Time[i]) {
  2210.             numberOfBars++;
  2211.          }
  2212.       }
  2213.  
  2214.       return(numberOfBars);
  2215.    }
  2216.  
  2217.    return(-1);
  2218. }
  2219.  
  2220.  
  2221. //+------------------------------------------------------------------+
  2222.  
  2223. int sqGetLastOrderType(string symbol, int magicNumber, string comment) {
  2224.    ulong ticket = sqSelectDeal(magicNumber, symbol, 0, comment);
  2225.    if(ticket > 0) {
  2226.       ENUM_DEAL_TYPE dealType = HistoryDealGetInteger(ticket, DEAL_TYPE);
  2227.      
  2228.       if(dealType == DEAL_TYPE_BUY) {
  2229.          return(1);
  2230.       } else {
  2231.          return(-1);
  2232.       }
  2233.    }
  2234.  
  2235.    return(0);
  2236. }
  2237.  
  2238. //+------------------------------------------------------------------+
  2239.  
  2240. ulong sqSelectDeal(int magicNumber, string symbol, int direction, string comment) {
  2241.    HistorySelect(startTime, getTime(0));
  2242.  
  2243.    for(int i=HistoryDealsTotal() - 1; i>=0; i--) {
  2244.       ulong ticket = HistoryDealGetTicket(i);
  2245.      
  2246.       if (dealFits(ticket, symbol, magicNumber, direction, comment)) {
  2247.          return(ticket);
  2248.       }
  2249.    }
  2250.  
  2251.    return(0);
  2252. }
  2253.  
  2254. //+------------------------------------------------------------------+
  2255.  
  2256. double sqConvertToPips(string symbol, double value) {
  2257.    if(symbol == "NULL" || symbol == "Current") {
  2258.       return(gPointPow * value);
  2259.    }
  2260.  
  2261.    // recognize point coeficient
  2262.    int realDigits = SymbolInfoInteger(symbol, SYMBOL_DIGITS);
  2263.    if(realDigits == 4 || realDigits == 5) {
  2264.       realDigits -= 1;
  2265.    }
  2266.  
  2267.    double pointPow = MathPow(10, realDigits);
  2268.  
  2269.    return(pointPow * value);
  2270. }
  2271.  
  2272. //+------------------------------------------------------------------+
  2273.  
  2274. bool sqSelectPendingOrderByType(int magicNo, string symbol, int type, string comment) {
  2275.    Alert("-------- orders total: ", OrdersTotal());
  2276.  
  2277.    for (int cc = OrdersTotal() - 1; cc >= 0; cc--) {
  2278.       ulong ticket = OrderGetTicket(cc);
  2279.      
  2280.       if (OrderSelect(ticket)) {
  2281.          ENUM_ORDER_TYPE orderType = OrderGetInteger(ORDER_TYPE);
  2282.          string orderSymbol = OrderGetString(ORDER_SYMBOL);        
  2283.          string orderComment = OrderGetString(ORDER_COMMENT);
  2284.          int orderMagicNumber = OrderGetInteger(ORDER_MAGIC);
  2285.          
  2286.          if(type != 0) {
  2287.             if(orderType != type) continue;
  2288.          }
  2289.  
  2290.          if(magicNo > 0) {
  2291.             if(orderMagicNumber != magicNo) continue;
  2292.          }
  2293.        
  2294.          if(symbol != "Any") {
  2295.             if(symbol == "NULL" || symbol == "Current") {
  2296.                symbol = Symbol();
  2297.             }
  2298.    
  2299.             if(orderSymbol != symbol) continue;
  2300.          }
  2301.    
  2302.          if(comment != "" && comment != NULL) {
  2303.            if(StringFind(orderComment, comment) == -1) continue;
  2304.           }
  2305.  
  2306.          // otherwise we found the order
  2307.          return(true);
  2308.       }
  2309.    }
  2310.  
  2311.    return(false);
  2312. }
  2313. /*
  2314. //+------------------------------------------------------------------+
  2315.  
  2316. bool sqSelectPendingOrderByDir(int magicNumber, string symbol, int direction, string comment) {
  2317.    for (int cc = OrdersTotal() - 1; cc >= 0; cc--) {
  2318.       ulong ticket = OrderGetTicket(cc);
  2319.      
  2320.       if (OrderSelect(ticket)) {
  2321.          ENUM_ORDER_TYPE orderType = OrderGetInteger(ORDER_TYPE);
  2322.          string orderSymbol = OrderGetString(ORDER_SYMBOL);        
  2323.          string orderComment = OrderGetString(ORDER_COMMENT);
  2324.          double orderVolume = OrderGetDouble(ORDER_VOLUME_INITIAL);
  2325.          double orderOpenPrice = OrderGetDouble(ORDER_PRICE_OPEN);
  2326.          double orderCurrentPrice = OrderGetDouble(ORDER_PRICE_CURRENT);
  2327.          int orderMagicNumber = OrderGetInteger(ORDER_MAGIC);
  2328.          
  2329.          if(direction != 0) {
  2330.             if(direction > 0 && orderType != ORDER_TYPE_BUY_STOP && orderType != ORDER_TYPE_BUY_LIMIT) continue;
  2331.             if(direction < 0 && orderType != ORDER_TYPE_SELL_STOP && orderType != ORDER_TYPE_SELL_LIMIT) continue;
  2332.          }
  2333.  
  2334.          if(magicNumber != 0) {
  2335.             if(orderMagicNumber != magicNumber) continue;
  2336.          }
  2337.  
  2338.        if(symbol != "Any") {
  2339.          if(symbol == "NULL" || symbol == "Current") {
  2340.             symbol = Symbol();
  2341.          }
  2342.  
  2343.          if(orderSymbol != symbol) continue;
  2344.        }
  2345.  
  2346.        if(comment != "") {
  2347.          if(StringFind(orderComment, comment) == -1) continue;
  2348.        }
  2349.  
  2350.        // otherwise we found the order
  2351.        return(true);
  2352.      }
  2353.    }
  2354.  
  2355.    return(false);
  2356. }
  2357.  
  2358. //+------------------------------------------------------------------+
  2359. */
  2360. bool sqDeletePendingOrder(int ticket) {
  2361.    Verbose(" Deleting pending order, ticket: " + ticket);
  2362.  
  2363.    ENUM_ORDER_TYPE orderType = OrderGetInteger(ORDER_TYPE);
  2364.  
  2365.    if(orderType == ORDER_TYPE_BUY || orderType == ORDER_TYPE_SELL) {
  2366.       Verbose("Trying to delete non-pending order");
  2367.       return(false);
  2368.    }
  2369.    if(!sqCheckConnected()) {
  2370.       return(false);
  2371.    }
  2372.  
  2373.    GetLastError(); // clear the global variable.
  2374.    int error = 0;
  2375.    int retries = 0;
  2376.    bool result;
  2377.  
  2378.    while (true) {
  2379.       if (IsTradeAllowed()) {
  2380.          result = OrderDelete(ticket);                                  
  2381.          if(result) {
  2382.             Verbose("Order deleted successfuly");
  2383.             return(true);
  2384.          }
  2385.       }
  2386.  
  2387.       retries++;
  2388.       if(!sqProcessErrors(retries, GetLastError())) {
  2389.          return(-1);
  2390.       }
  2391.    }
  2392. }
  2393.  
  2394. bool OrderDelete(ulong ticket){
  2395.    ZeroMemory(mrequest);
  2396.    
  2397.    mrequest.action = TRADE_ACTION_REMOVE;
  2398.    mrequest.magic = magicNumber;
  2399.    mrequest.order = ticket;
  2400.    //--- action and return the result
  2401.    return(OrderSend(mrequest, mresult));
  2402. }
  2403.  
  2404. bool IsTesting(){
  2405.    return MQLInfoInteger(MQL_TESTER);
  2406. }
  2407.  
  2408. //+------------------------------------------------------------------+
  2409.  
  2410. double sleepPeriod = 500; // 0.5 s
  2411. double maxSleepPeriod = 20000; // 20 s.
  2412.  
  2413. void sqSleep() {
  2414.    if(IsTesting()) return;
  2415.  
  2416.    Sleep(sleepPeriod);
  2417.  
  2418.    int periods = maxSleepPeriod / sleepPeriod;
  2419.  
  2420.    for(int i=0; i<periods; i++) {
  2421.       if (MathRand() > 16383) {
  2422.          // 50% chance of quitting
  2423.          break;
  2424.       }
  2425.  
  2426.       Sleep(sleepPeriod);
  2427.    }
  2428. }
  2429.  
  2430. int sqGetDirectionFromOrderType(int orderType) {
  2431.    if(orderType == ORDER_TYPE_BUY || orderType == ORDER_TYPE_BUY_STOP || orderType == ORDER_TYPE_BUY_LIMIT) {
  2432.       return(1);
  2433.    } else {
  2434.       return(-1);
  2435.    }
  2436. }
  2437.  
  2438. //+------------------------------------------------------------------+
  2439.  
  2440. bool sqIsPendingOrder(int orderType) {
  2441.    if(orderType != ORDER_TYPE_BUY && orderType != ORDER_TYPE_SELL) {
  2442.       return(true);
  2443.    }
  2444.    return(false);
  2445. }
  2446.  
  2447. //+------------------------------------------------------------------+
  2448.  
  2449. string sqGetOrderTypeAsString(int type) {
  2450.    switch(type) {
  2451.       case ORDER_TYPE_BUY: return("Buy");
  2452.       case ORDER_TYPE_SELL: return("Sell");
  2453.       case ORDER_TYPE_BUY_LIMIT: return("Buy Limit");
  2454.       case ORDER_TYPE_BUY_STOP: return("Buy Stop");
  2455.       case ORDER_TYPE_SELL_LIMIT: return("Sell Limit");
  2456.       case ORDER_TYPE_SELL_STOP: return("Sell Stop");
  2457.    }
  2458.  
  2459.    return("Unknown");
  2460. }
  2461.  
  2462. //+------------------------------------------------------------------+
  2463.  
  2464. void sqInitInfoPanel() {
  2465.       ObjectCreate(ChartID(), "line1", OBJ_LABEL, 0, 0, 0);
  2466.       ObjectSetInteger(ChartID(), "line1", OBJPROP_CORNER, sqLabelCorner);
  2467.       ObjectSetInteger(ChartID(), "line1", OBJPROP_YDISTANCE, sqOffsetVertical + 0);
  2468.       ObjectSetInteger(ChartID(), "line1", OBJPROP_XDISTANCE, sqOffsetHorizontal);
  2469.       setupLabel("line1", sqStrategyName, 9);
  2470.  
  2471.       ObjectCreate(ChartID(), "linec", OBJ_LABEL, 0, 0, 0);
  2472.       ObjectSetInteger(ChartID(), "linec", OBJPROP_CORNER, sqLabelCorner);
  2473.       ObjectSetInteger(ChartID(), "linec", OBJPROP_YDISTANCE, sqOffsetVertical + 16 );
  2474.       ObjectSetInteger(ChartID(), "linec", OBJPROP_XDISTANCE, sqOffsetHorizontal);
  2475.       setupLabel("linec", "Generated by StrategyQuant EA Wizard");
  2476.  
  2477.       ObjectCreate(ChartID(), "line2", OBJ_LABEL, 0, 0, 0);
  2478.       ObjectSetInteger(ChartID(), "line2", OBJPROP_CORNER, sqLabelCorner);
  2479.       ObjectSetInteger(ChartID(), "line2", OBJPROP_YDISTANCE, sqOffsetVertical + 28);
  2480.       ObjectSetInteger(ChartID(), "line2", OBJPROP_XDISTANCE, sqOffsetHorizontal);
  2481.       setupLabel("line2", "------------------------------------------");
  2482.  
  2483.       ObjectCreate(ChartID(), "lines", OBJ_LABEL, 0, 0, 0);
  2484.       ObjectSetInteger(ChartID(), "lines", OBJPROP_CORNER, sqLabelCorner);
  2485.       ObjectSetInteger(ChartID(), "lines", OBJPROP_YDISTANCE, sqOffsetVertical + 44);
  2486.       ObjectSetInteger(ChartID(), "lines", OBJPROP_XDISTANCE, sqOffsetHorizontal);
  2487.       setupLabel("lines", "Last Signal:  -", 9);
  2488.  
  2489.       ObjectCreate(ChartID(), "lineopl", OBJ_LABEL, 0, 0, 0);
  2490.       ObjectSetInteger(ChartID(), "lineopl", OBJPROP_CORNER, sqLabelCorner);
  2491.       ObjectSetInteger(ChartID(), "lineopl", OBJPROP_YDISTANCE, sqOffsetVertical + 60);
  2492.       ObjectSetInteger(ChartID(), "lineopl", OBJPROP_XDISTANCE, sqOffsetHorizontal);
  2493.       setupLabel("lineopl", "Open P/L: -");
  2494.  
  2495.       ObjectCreate(ChartID(), "linea", OBJ_LABEL, 0, 0, 0);
  2496.       ObjectSetInteger(ChartID(), "linea", OBJPROP_CORNER, sqLabelCorner);
  2497.       ObjectSetInteger(ChartID(), "linea", OBJPROP_YDISTANCE, sqOffsetVertical + 76);
  2498.       ObjectSetInteger(ChartID(), "linea", OBJPROP_XDISTANCE, sqOffsetHorizontal);
  2499.       setupLabel("linea", "Account Balance: -");
  2500.  
  2501.       ObjectCreate(ChartID(), "lineto", OBJ_LABEL, 0, 0, 0);
  2502.       ObjectSetInteger(ChartID(), "lineto", OBJPROP_CORNER, sqLabelCorner);
  2503.       ObjectSetInteger(ChartID(), "lineto", OBJPROP_YDISTANCE, sqOffsetVertical + 92);
  2504.       ObjectSetInteger(ChartID(), "lineto", OBJPROP_XDISTANCE, sqOffsetHorizontal);
  2505.       setupLabel("lineto", "Total profits/losses so far: -/-");
  2506.  
  2507.       ObjectCreate(ChartID(), "linetp", OBJ_LABEL, 0, 0, 0);
  2508.       ObjectSetInteger(ChartID(), "linetp", OBJPROP_CORNER, sqLabelCorner);
  2509.       ObjectSetInteger(ChartID(), "linetp", OBJPROP_YDISTANCE, sqOffsetVertical + 108);
  2510.       ObjectSetInteger(ChartID(), "linetp", OBJPROP_XDISTANCE, sqOffsetHorizontal);
  2511.       setupLabel("linetp", "Total P/L so far: -");
  2512. }
  2513.  
  2514. //+------------------------------------------------------------------+
  2515.  
  2516. void sqDeinitInfoPanel() {
  2517.    ObjectDelete(ChartID(), "line1");
  2518.    ObjectDelete(ChartID(), "linec");
  2519.    ObjectDelete(ChartID(), "line2");
  2520.    ObjectDelete(ChartID(), "lines");
  2521.    ObjectDelete(ChartID(), "lineopl");
  2522.    ObjectDelete(ChartID(), "linea");
  2523.    ObjectDelete(ChartID(), "lineto");
  2524.    ObjectDelete(ChartID(), "linetp");
  2525. }
  2526.  
  2527. //+------------------------------------------------------------------+
  2528.  
  2529. void sqTextFillOpens() {
  2530.    setupLabel("lineopl", "Open P/L: "+DoubleToString(sqGetOpenPLInMoney(0), 2));
  2531.    setupLabel("linea", "Account Balance: "+DoubleToString(AccountInfoDouble(ACCOUNT_BALANCE), 2));
  2532. }
  2533.  
  2534. //+------------------------------------------------------------------+
  2535.  
  2536. void setupLabel(string objectName, string text, const string font = "Tahoma", const int fontSize = 8, const color objColor = NULL){
  2537.    color clr = objColor == NULL ? sqLabelColor : objColor;
  2538.    
  2539.    ObjectSetString(ChartID(), objectName, OBJPROP_TEXT, text);
  2540.    ObjectSetString(ChartID(), objectName, OBJPROP_FONT, font);
  2541.    ObjectSetInteger(ChartID(), objectName, OBJPROP_FONTSIZE, fontSize);
  2542.    ObjectSetInteger(ChartID(), objectName, OBJPROP_COLOR, clr);
  2543. }
  2544.  
  2545. //+------------------------------------------------------------------+
  2546.  
  2547. void sqTextFillTotals() {
  2548.    setupLabel("lineto", "Total profits/losses so far: "+sqGetTotalProfits(0, 100)+"/"+sqGetTotalLosses(0, 100));
  2549.    setupLabel("linetp", "Total P/L so far: "+DoubleToString(sqGetTotalClosedPLInMoney(0, 1000), 2));
  2550. }
  2551.  
  2552.  
  2553. //+------------------------------------------------------------------+
  2554.  
  2555. double sqGetOpenPLInMoney(int orderMagicNumber) {
  2556.    double pl = 0;
  2557.  
  2558.    for(int i=PositionsTotal(); i>=0; i--) {
  2559.       ulong ticket = PositionGetTicket(i);
  2560.      
  2561.       if(PositionSelectByTicket(ticket)){
  2562.          int magic = PositionGetInteger(POSITION_MAGIC);
  2563.          double profit = PositionGetDouble(POSITION_PROFIT);
  2564.          
  2565.          if(orderMagicNumber != 0 && magic != orderMagicNumber) continue;
  2566.          
  2567.          pl += profit;
  2568.       }
  2569.    }
  2570.  
  2571.    return(pl);
  2572. }
  2573.  
  2574. //+------------------------------------------------------------------+
  2575.  
  2576. int sqGetTotalProfits(int orderMagicNumber, int numberOfLastOrders) {
  2577.    int count = 0;
  2578.    int profits = 0;
  2579.  
  2580.    HistorySelect(startTime, getTime(0));
  2581.  
  2582.    for(int i=HistoryDealsTotal(); i>=0; i--) {
  2583.       ulong ticket = HistoryDealGetTicket(i);
  2584.      
  2585.       if (HistoryDealGetString(ticket, DEAL_SYMBOL) == Symbol() && HistoryDealGetInteger(ticket,DEAL_ENTRY) == DEAL_ENTRY_OUT) {
  2586.          int magic = HistoryDealGetInteger(ticket, DEAL_MAGIC);
  2587.          
  2588.          if(orderMagicNumber == 0 || magic == orderMagicNumber) {
  2589.             // return the P/L of last order
  2590.             // or return the P/L of last order with given Magic Number
  2591.             count++;
  2592.  
  2593.             if(HistoryDealGetDouble(ticket, DEAL_PROFIT) > 0) {
  2594.                profits++;
  2595.             }
  2596.  
  2597.             if(count >= numberOfLastOrders) break;
  2598.          }
  2599.       }
  2600.    }
  2601.  
  2602.    return(profits);
  2603. }
  2604.  
  2605. //+------------------------------------------------------------------+
  2606.  
  2607. int sqGetTotalLosses(int orderMagicNumber, int numberOfLastOrders) {
  2608.    int count = 0;
  2609.    int losses = 0;
  2610.    
  2611.    HistorySelect(startTime, getTime(0));
  2612.  
  2613.    for(int i=HistoryDealsTotal(); i>=0; i--) {
  2614.       ulong ticket = HistoryDealGetTicket(i);
  2615.      
  2616.       if (HistoryDealGetString(ticket, DEAL_SYMBOL) == Symbol() && HistoryDealGetInteger(ticket,DEAL_ENTRY) == DEAL_ENTRY_OUT) {
  2617.          int magic = HistoryDealGetInteger(ticket, DEAL_MAGIC);
  2618.          
  2619.          if(orderMagicNumber == 0 || magic == orderMagicNumber) {
  2620.             // return the P/L of last order
  2621.             // or return the P/L of last order with given Magic Number
  2622.             count++;
  2623.            
  2624.             if(HistoryDealGetDouble(ticket, DEAL_PROFIT) < 0) {
  2625.                losses++;
  2626.             }
  2627.  
  2628.             if(count >= numberOfLastOrders) break;
  2629.          }
  2630.       }
  2631.    }
  2632.  
  2633.    return(losses);
  2634. }
  2635.  
  2636.  
  2637. //+------------------------------------------------------------------+
  2638.  
  2639. double sqGetTotalClosedPLInMoney(int orderMagicNumber, int numberOfLastOrders) {
  2640.    double pl = 0;
  2641.    int count = 0;
  2642.    
  2643.    HistorySelect(startTime, getTime(0));
  2644.  
  2645.    for(int i=HistoryDealsTotal(); i>=0; i--) {
  2646.       ulong ticket = HistoryDealGetTicket(i);
  2647.      
  2648.       if (HistoryDealGetString(ticket, DEAL_SYMBOL) == Symbol() && HistoryDealGetInteger(ticket,DEAL_ENTRY) == DEAL_ENTRY_OUT) {
  2649.          int magic = HistoryDealGetInteger(ticket, DEAL_MAGIC);
  2650.          
  2651.          if(orderMagicNumber == 0 || magic == orderMagicNumber) {
  2652.             // return the P/L of last order or the P/L of last order with given Magic Number
  2653.            
  2654.             count++;
  2655.             pl = pl + HistoryDealGetDouble(ticket, DEAL_PROFIT);
  2656.  
  2657.             if(count >= numberOfLastOrders) break;
  2658.          }
  2659.       }
  2660.    }
  2661.    
  2662.    return(pl);
  2663. }
  2664.  
  2665. //+------------------------------------------------------------------+
  2666.  
  2667. double sqMMRiskPercentage(string symbol, int orderType, double price, double sl, double RiskInPercent, double LotsIfNoMM, double MaximumLots, double BaseCurrencyExchangeRate) {
  2668.    Verbose("Computing Money Management for order -  Risk fixed % of account balance");
  2669.    double slSize = sqConvertToPips(symbol, MathAbs(price - sl));
  2670.    
  2671.    if(slSize <= 0) {
  2672.       Verbose("Computing Money Management - Stop Loss is zero, using Lots if no MM: ", LotsIfNoMM);
  2673.       return(LotsIfNoMM);
  2674.    }
  2675.    Verbose("Price: ", price, ", SL: ", sl, ", SLSize: ", slSize, ", RiskInPercent: ", RiskInPercent);
  2676.  
  2677.    double LotSize=0;
  2678.  
  2679.    if(RiskInPercent < 0 ) {
  2680.       Verbose("Computing Money Management - Incorrect RiskInPercent size, it must be above 0");
  2681.       return(0);
  2682.    }
  2683.  
  2684.    double riskPerTrade = (BaseCurrencyExchangeRate * AccountInfoDouble(ACCOUNT_BALANCE) *  (RiskInPercent / 100.0));
  2685.    if(slSize <= 0) {
  2686.       Verbose("Computing Money Management - Incorrect StopLossPips size, it must be above 0");
  2687.       return(0);
  2688.    }
  2689.    Verbose("Risk per trade: ", riskPerTrade);
  2690.  
  2691.    
  2692.    double TickSize = SymbolInfoDouble(Symbol(), SYMBOL_TRADE_TICK_SIZE);
  2693.    double TickValue = SymbolInfoDouble(Symbol(), SYMBOL_TRADE_TICK_VALUE);
  2694.    double PointValue = SymbolInfoDouble(Symbol(), SYMBOL_POINT);
  2695.    double LotStep = SymbolInfoDouble(Symbol(), SYMBOL_VOLUME_STEP);
  2696.  
  2697.    if(_Digits == 1 || _Digits == 3 || _Digits == 5) {
  2698.       slSize = 10 * slSize; // conversion from pips to points
  2699.    }
  2700.  
  2701.    Verbose("Computing Money Management - SL: ", slSize, ", Account Balance: ", AccountInfoDouble(ACCOUNT_BALANCE),", Tick value: ", TickValue,", Point: ", PointValue, ", LotStep: ", LotStep,", Tick size: ", TickSize);
  2702.  
  2703.  
  2704.    if(slSize>0 && TickValue>0)
  2705.    {
  2706.       LotSize = TickSize * riskPerTrade / (slSize * TickValue * PointValue );
  2707.  
  2708.       int err=GetLastError();
  2709.       if(err==4013)
  2710.       { //ERR_ZERO_DIVIDE
  2711.          Verbose("Err: division by zero: StopLoss:",slSize," TickValue:",TickValue," LotSize:",LotSize);
  2712.          return(-1);
  2713.       }
  2714.    }
  2715.  
  2716.    //--- MAXLOT and MINLOT management
  2717.    double Smallest_Lot = SymbolInfoDouble(Symbol(), SYMBOL_VOLUME_MIN);
  2718.    double Largest_Lot = SymbolInfoDouble(Symbol(), SYMBOL_VOLUME_MAX);
  2719.  
  2720.    Verbose("Computing Money Management - Smallest_Lot: ", Smallest_Lot, ", Largest_Lot: ", Largest_Lot,", Computed LotSize: ", LotSize);
  2721.  
  2722.    if (LotSize < Smallest_Lot) LotSize = Smallest_Lot;
  2723.    if (LotSize > Largest_Lot) LotSize = Largest_Lot;
  2724.  
  2725.    if(LotSize > MaximumLots) {
  2726.       LotSize = MaximumLots;
  2727.    }
  2728.  
  2729.    //--------------------------------------------
  2730.    //--- LotSize rounded regarding Broker LOTSTEP
  2731.  
  2732.    if(LotStep==1) {
  2733.       LotSize=NormalizeDouble(LotSize,0);
  2734.    }
  2735.    if(LotStep==0.1) {
  2736.       LotSize=NormalizeDouble(LotSize,1);
  2737.    }
  2738.    if(LotStep==0.01) {
  2739.       LotSize=NormalizeDouble(LotSize,2);
  2740.    }
  2741.    if(LotStep==0.001) {
  2742.       LotSize=NormalizeDouble(LotSize,3);
  2743.    }
  2744.  
  2745.    //--------------------------------------------
  2746.  
  2747.    return (LotSize);
  2748. }
  2749.  
  2750. //+------------------------------------------------------------------+
  2751.  
  2752. double sqGetSLLevel(string symbol, int orderType, double price, bool valueInPips, double value) {
  2753.    return(sqGetSLPTLevel(-1.0, symbol, orderType, price, valueInPips, value));
  2754. }
  2755.  
  2756. //+------------------------------------------------------------------+
  2757.  
  2758. double sqGetPTLevel(string symbol, int orderType, double price, bool valueInPips, double value) {
  2759.    return(sqGetSLPTLevel(1.0, symbol, orderType, price, valueInPips, value));
  2760. }
  2761.  
  2762. //+------------------------------------------------------------------+
  2763.  
  2764. double sqGetSLPTLevel(double SLorPT, string symbol, int orderType, double price, bool valueInPips, double value) {
  2765.    string _symbol = correctSymbol(symbol);
  2766.  
  2767.    if(valueInPips) {
  2768.       // convert from pips to real points
  2769.       value = sqConvertToRealPips(_symbol, value);
  2770.    }
  2771.    
  2772.    if(price == 0) {
  2773.       // price can be zero for market order
  2774.       if(orderType == ORDER_TYPE_BUY) {
  2775.          price = sqGetAsk(_symbol);
  2776.       } else {
  2777.          price = sqGetBid(_symbol);
  2778.       }
  2779.    }
  2780.    
  2781.    if(orderType == ORDER_TYPE_BUY || orderType == ORDER_TYPE_BUY_STOP || orderType == ORDER_TYPE_BUY_LIMIT) {
  2782.       return (price + (SLorPT * value));
  2783.    } else {
  2784.       return (price - (SLorPT * value));
  2785.    }
  2786. }
  2787.  
  2788. //+------------------------------------------------------------------+
  2789.  
  2790. double sqBarRange(string symbol, int timeframe, int shift) {
  2791.    string curSymbol = (symbol == "NULL" || symbol == "Current") ? _Symbol : symbol;
  2792.  
  2793.    return(iHigh(curSymbol, timeframe, shift) - iLow(symbol, timeframe, shift));
  2794. }
  2795.  
  2796. //+------------------------------------------------------------------+
  2797.  
  2798. double sqConvertToRealPips(string symbol, double value) {
  2799.    if(symbol == "NULL" || symbol == "Current") {
  2800.       return(gPointCoef * value);
  2801.    }
  2802.  
  2803.    double pointCoef = sqGetPointCoef(symbol);
  2804.  
  2805.    return(pointCoef * value);
  2806. }
  2807.  
  2808. //+------------------------------------------------------------------+
  2809.  
  2810. double sqGetPointCoef(string symbol) {
  2811.    if(symbol == "NULL" || symbol == "Current") {
  2812.       return(gPointCoef);
  2813.    }
  2814.  
  2815.    // recognize point coeficient
  2816.    double realDigits = SymbolInfoInteger(symbol, SYMBOL_DIGITS);
  2817.    if(realDigits == 4 || realDigits == 5) {
  2818.       realDigits -= 1;
  2819.    }
  2820.  
  2821.    double pointPow = MathPow(10, realDigits);
  2822.  
  2823.    return(1 / pointPow);
  2824. }
  2825.  
  2826.  
  2827. //+------------------------------------------------------------------+
  2828.  
  2829. bool sqDoublesAreEqual(double n1, double n2) {
  2830.    string st1 = DoubleToString(n1, _Digits);
  2831.    string st2 = DoubleToString(n2, _Digits);
  2832.  
  2833.    return (st1 == st2);
  2834. }
  2835.  
  2836. //+------------------------------------------------------------------+
  2837.  
  2838. double sqHighest(string symbol, int timeframe, int period, int shift) {
  2839.    double maxnum = -100000000;
  2840.    double val;
  2841.  
  2842.    for(int i=shift; i<shift+period; i++) {
  2843.       if(symbol == NULL || symbol == "NULL" || symbol == "Current") {
  2844.          val = iHigh(NULL, timeframe, i);
  2845.       } else {
  2846.          val = iHigh(symbol, timeframe, i);
  2847.       }
  2848.  
  2849.       if(val > maxnum) {
  2850.          maxnum = val;
  2851.       }
  2852.    }
  2853.  
  2854.    return(maxnum);
  2855. }
  2856.  
  2857. //+------------------------------------------------------------------+
  2858.  
  2859. double sqHighestIndex(string symbol, int timeframe, int period, int shift) {
  2860.    double maxnum = -100000000;
  2861.    int index;
  2862.    double val;
  2863.  
  2864.    for(int i=shift; i<shift+period; i++) {
  2865.       if(symbol == NULL || symbol == "NULL" || symbol == "Current") {
  2866.          val = iHigh(NULL, timeframe, i);
  2867.       } else {
  2868.          val = iHigh(symbol, timeframe, i);
  2869.       }
  2870.  
  2871.       if(val > maxnum) {
  2872.          maxnum = val;
  2873.          index = i;
  2874.       }
  2875.    }
  2876.  
  2877.    return(index);
  2878. }
  2879.  
  2880. //+------------------------------------------------------------------+
  2881.  
  2882. double sqLowest(string symbol, int timeframe, int period, int shift) {
  2883.    double minnum = 100000000;
  2884.    double val;
  2885.  
  2886.    for(int i=shift; i<shift+period; i++) {
  2887.       if(symbol == NULL || symbol == "NULL" || symbol == "Current") {
  2888.          val = iLow(NULL, timeframe, i);
  2889.       } else {
  2890.          val = iLow(symbol, timeframe, i);
  2891.       }
  2892.  
  2893.       if(val < minnum) {
  2894.          minnum = val;
  2895.       }
  2896.    }
  2897.  
  2898.    return(minnum);
  2899. }
  2900.  
  2901. //+------------------------------------------------------------------+
  2902.  
  2903. double sqLowestIndex(string symbol, int timeframe, int period, int shift) {
  2904.    double minnum = 100000000;
  2905.    int index;
  2906.    double val;
  2907.  
  2908.    for(int i=shift; i<shift+period; i++) {
  2909.       if(symbol == NULL || symbol == "NULL" || symbol == "Current") {
  2910.          val = iLow(NULL, timeframe, i);
  2911.       } else {
  2912.          val = iLow(symbol, timeframe, i);
  2913.       }
  2914.  
  2915.       if(val < minnum) {
  2916.          minnum = val;
  2917.          index = i;
  2918.       }
  2919.    }
  2920.  
  2921.    return(index);
  2922. }
  2923.  
  2924. //+------------------------------------------------------------------+
  2925.  
  2926. double sqBiggestRange(string symbol, int timeframe, int period, int shift) {
  2927.    double maxnum = -100000000;
  2928.    double range;
  2929.  
  2930.    for(int i=shift; i<shift+period; i++) {
  2931.       if(symbol == NULL || symbol == "NULL" || symbol == "Current") {
  2932.          range = iHigh(NULL, timeframe, i) - iLow(NULL, timeframe, i);
  2933.       } else {
  2934.          range = iHigh(symbol, timeframe, i) - iLow(symbol, timeframe, i);
  2935.       }
  2936.  
  2937.       if(range > maxnum) {
  2938.          maxnum = range;
  2939.       }
  2940.    }
  2941.  
  2942.    return(maxnum);
  2943. }
  2944.  
  2945.  
  2946. //+------------------------------------------------------------------+
  2947.  
  2948. double sqSmallestRange(string symbol, int timeframe, int period, int shift) {
  2949.    double minnum = 100000000;
  2950.    double range;
  2951.  
  2952.    for(int i=shift; i<shift+period; i++) {
  2953.       if(symbol == NULL || symbol == "NULL" || symbol == "Current") {
  2954.          range = iHigh(NULL, timeframe, i) - iLow(NULL, timeframe, i);
  2955.       } else {
  2956.          range = iHigh(symbol, timeframe, i) - iLow(symbol, timeframe, i);
  2957.       }
  2958.  
  2959.       if(range < minnum) {
  2960.          minnum = range;
  2961.       }
  2962.    }
  2963.  
  2964.    return(minnum);
  2965. }
  2966.  
  2967. //+------------------------------------------------------------------+
  2968.  
  2969. void sqDrawUpArrow(int shift) {
  2970.    string name;
  2971.    StringConcatenate(name, "Arrow_", MathRand());
  2972.  
  2973.    ObjectCreate(ChartID(), name, OBJ_ARROW, 0, getTime(shift), getHigh(shift) - 20 * _Point); //draw an up arrow
  2974.    ObjectSetInteger(ChartID(), name, OBJPROP_STYLE, STYLE_SOLID);
  2975.    ObjectSetInteger(ChartID(), name, OBJPROP_ARROWCODE, OBJ_ARROW_UP);
  2976.    ObjectSetInteger(ChartID(), name, OBJPROP_COLOR, clrGreen);
  2977. }
  2978.  
  2979. //+------------------------------------------------------------------+
  2980.  
  2981. void sqDrawDownArrow(int shift) {
  2982.    string name;
  2983.    StringConcatenate(name, "Arrow_", MathRand());
  2984.  
  2985.    ObjectCreate(ChartID(), name, OBJ_ARROW, 0, getTime(shift), getHigh(shift) + 140 * _Point); //draw an down arrow
  2986.    ObjectSetInteger(ChartID(), name, OBJPROP_STYLE, STYLE_SOLID);
  2987.    ObjectSetInteger(ChartID(), name, OBJPROP_ARROWCODE, OBJ_ARROW_DOWN);
  2988.    ObjectSetInteger(ChartID(), name, OBJPROP_COLOR, clrRed);
  2989. }
  2990.  
  2991. //+------------------------------------------------------------------+
  2992.  
  2993. double sqHeikenAshi(string symbol, ENUM_TIMEFRAMES timeframe, string mode, int shift) {
  2994.    int handle = iCustom(correctSymbol(symbol), timeframe, "Examples\\Heiken_Ashi", 0,0,0,0);
  2995.    
  2996.    if(mode == "Open") {
  2997.       return(sqGetIndicatorValue(handle, 0, shift));
  2998.    }
  2999.    else if(mode == "Close") {
  3000.       return(sqGetIndicatorValue(handle, 3, shift));
  3001.    }
  3002.    else if(mode == "High") {
  3003.       return(MathMax(sqGetIndicatorValue(handle, 0, shift), sqGetIndicatorValue(handle, 1, shift)));
  3004.    }
  3005.    else if(mode == "Low") {
  3006.       return(MathMin(sqGetIndicatorValue(handle, 0, shift), sqGetIndicatorValue(handle, 2, shift)));
  3007.    }
  3008.  
  3009.    return(-1);
  3010. }
  3011.  
  3012. //+------------------------------------------------------------------+
  3013.  
  3014. double sqDaily(string symbol, int tf, string mode, int shift) {
  3015.    if(symbol == "NULL" || symbol == "Current") {
  3016.       if(mode == "Open") {
  3017.          return(iOpen(NULL, PERIOD_D1, shift));
  3018.       }
  3019.       if(mode == "Close") {
  3020.          return(iClose(NULL, PERIOD_D1, shift));
  3021.       }
  3022.       if(mode == "High") {
  3023.          return(iHigh(NULL, PERIOD_D1, shift));
  3024.       }
  3025.       if(mode == "Low") {
  3026.          return(iLow(NULL, PERIOD_D1, shift));
  3027.       }
  3028.  
  3029.    } else {
  3030.       if(mode == "Open") {
  3031.          return(iOpen(symbol, PERIOD_D1, shift));
  3032.       }
  3033.       if(mode == "Close") {
  3034.          return(iClose(symbol, PERIOD_D1, shift));
  3035.       }
  3036.       if(mode == "High") {
  3037.          return(iHigh(symbol, PERIOD_D1, shift));
  3038.       }
  3039.       if(mode == "Low") {
  3040.          return(iLow(symbol, PERIOD_D1, shift));
  3041.       }
  3042.    }
  3043.  
  3044.    return(-1);
  3045. }
  3046.  
  3047. //+------------------------------------------------------------------+
  3048.  
  3049. double sqHighestInRange(string symbol, int timeframe, string timeFrom, string timeTo) {
  3050.    int indexTo = -1;
  3051.    int indexFrom = -1;
  3052.    int i;
  3053.  
  3054.    // find index of bar for timeTo
  3055.    for(i=1; i<=2000; i++) {
  3056.       if(TimeToString(getTime(i), TIME_MINUTES) == timeTo || (TimeToString(getTime(i), TIME_MINUTES) >= timeTo && TimeToString(getTime(i+1), TIME_MINUTES) < timeTo)) {
  3057.          //Log("Found timeTo: ", TimeToString(Time[i]));
  3058.          indexTo = i;
  3059.          break;
  3060.       }
  3061.    }
  3062.  
  3063.    if(indexTo == -1) {
  3064.       Log("Not found timeTo");
  3065.       return(-1);
  3066.    }
  3067.  
  3068.    // find index of bar for timeFrom
  3069.    for(i=indexTo+1; i<=2000; i++) {
  3070.       if(TimeToString(getTime(i), TIME_MINUTES) == timeFrom || (TimeToString(getTime(i), TIME_MINUTES) >= timeFrom && TimeToString(getTime(i+1), TIME_MINUTES) < timeFrom)) {
  3071.          //Log("Found timeFrom: ", TimeToString(Time[i]));
  3072.          indexFrom = i;
  3073.          break;
  3074.       }
  3075.    }
  3076.  
  3077.    if(indexFrom == -1) {
  3078.       Log("Not found time From");
  3079.       return(-1);
  3080.    }
  3081.  
  3082.    double value = -100000000.0;
  3083.  
  3084.    for(i=indexTo; i<=indexFrom; i++) {
  3085.       if(symbol == "NULL") {
  3086.          value = MathMax(value, iHigh(NULL, timeframe, i));
  3087.       } else {
  3088.          value = MathMax(value, iHigh(symbol, timeframe, i));
  3089.       }
  3090.    }
  3091.  
  3092.    return(value);
  3093. }
  3094.  
  3095. //+------------------------------------------------------------------+
  3096.  
  3097. double sqLowestInRange(string symbol, int timeframe, string timeFrom, string timeTo) {
  3098.    int indexTo = -1;
  3099.    int indexFrom = -1;
  3100.    int i;
  3101.  
  3102.    // find index of bar for timeTo
  3103.    for(i=1; i<=2000; i++) {
  3104.       if(TimeToString(getTime(i), TIME_MINUTES) == timeTo || (TimeToString(getTime(i), TIME_MINUTES) >= timeTo && TimeToString(getTime(i+1), TIME_MINUTES) < timeTo)) {
  3105.          //Log("Found timeTo: ", TimeToString(Time[i]));
  3106.          indexTo = i;
  3107.          break;
  3108.       }
  3109.    }
  3110.  
  3111.    if(indexTo == -1) {
  3112.       Log("Not found timeTo");
  3113.       return(-1);
  3114.    }
  3115.  
  3116.    // find index of bar for timeFrom
  3117.    for(i=indexTo+1; i<=2000; i++) {
  3118.       if(TimeToString(getTime(i), TIME_MINUTES) == timeFrom || (TimeToString(getTime(i), TIME_MINUTES) >= timeFrom && TimeToString(getTime(i+1), TIME_MINUTES) < timeFrom)) {
  3119.          //Log("Found timeFrom: ", TimeToString(Time[i]));
  3120.          indexFrom = i;
  3121.          break;
  3122.       }
  3123.    }
  3124.  
  3125.    if(indexFrom == -1) {
  3126.       Log("Not found time From");
  3127.       return(-1);
  3128.    }
  3129.  
  3130.    double value = 100000000.0;
  3131.  
  3132.    for(i=indexTo; i<=indexFrom; i++) {
  3133.       if(symbol == "NULL") {
  3134.          value = MathMin(value, iLow(NULL, timeframe, i));
  3135.       } else {
  3136.          value = MathMin(value, iLow(symbol, timeframe, i));
  3137.       }
  3138.    }
  3139.  
  3140.    return(value);
  3141. }
  3142.  
  3143. //+------------------------------------------------------------------+
  3144.  
  3145. string sqGetDate(int day, int month, int year) {
  3146.    string strYear = year;
  3147.  
  3148.    string strMonth = month;
  3149.    if(month < 10) strMonth = "0"+strMonth;
  3150.  
  3151.    string strDay = day;
  3152.    if(day < 10) strDay = "0"+strDay;
  3153.  
  3154.    return(StringConcatenate(strYear, ".", strMonth, ".", strDay));
  3155. }
  3156.  
  3157. //+------------------------------------------------------------------+
  3158.  
  3159. string sqGetTime(int hour, int minute, int second) {
  3160.    string strHour = hour;
  3161.    if(hour < 10) strHour = "0"+strHour;
  3162.  
  3163.    string strMinute = minute;
  3164.    if(minute < 10) strMinute = "0"+strMinute;
  3165.  
  3166.    string strSecond = second;
  3167.    if(second < 10) strSecond = "0"+strSecond;
  3168.  
  3169.    return(StringConcatenate(strHour, ":", strMinute, ":", strSecond));
  3170. }
  3171.  
  3172. //+------------------------------------------------------------------+
  3173.  
  3174. double sqSafeDivide(double var1, double var2) {
  3175.    if(var2 == 0) return(100000000);
  3176.    return(var1/var2);
  3177. }
  3178.  
  3179. //+------------------------------------------------------------------+
  3180.  
  3181. bool sqIsGreaterThanZero(double value) {
  3182.    double diff = value - 0;
  3183.    if(diff > 0.0000000001) {
  3184.       return(true);
  3185.    }
  3186.    return(false);
  3187. }
  3188.  
  3189. //+------------------------------------------------------------------+
  3190.  
  3191. bool sqIsLowerThanZero(double value) {
  3192.    double diff = 0 - value;
  3193.    if(diff > 0.0000000001) {
  3194.       return(true);
  3195.    }
  3196.    return(false);
  3197. }
  3198.  
  3199. //+------------------------------------------------------------------+
  3200. //+ Candle Pattern functions
  3201. //+------------------------------------------------------------------+
  3202.  
  3203. bool sqBearishEngulfing(string symbol, int shift) {
  3204.    double O = getOpen(shift);
  3205.    double O1 = getOpen(shift+1);
  3206.    double C = getClose(shift);
  3207.    double C1 = getClose(shift+1);
  3208.  
  3209.    if ((C1>O1)&&(O>C)&&(O>=C1)&&(O1>=C)&&((O-C)>(C1-O1))) {
  3210.       return(true);
  3211.    }
  3212.  
  3213.    return(false);
  3214. }
  3215.  
  3216. //+------------------------------------------------------------------+
  3217.  
  3218. bool sqBullishEngulfing(string symbol, int shift) {
  3219.    double O = getOpen(shift);
  3220.    double O1 = getOpen(shift+1);
  3221.    double C = getClose(shift);
  3222.    double C1 = getClose(shift+1);
  3223.  
  3224.    if ((O1>C1)&&(C>O)&&(C>=O1)&&(C1>=O)&&((C-O)>(O1-C1))) {
  3225.       return(true);
  3226.    }
  3227.  
  3228.    return(false);
  3229. }
  3230.  
  3231. //+------------------------------------------------------------------+
  3232.  
  3233. bool sqDarkCloudCover(string symbol, int shift) {
  3234.    double L = getLow(shift);
  3235.    double H = getHigh(shift);
  3236.  
  3237.    double O = getOpen(shift);
  3238.    double O1 = getOpen(shift+1);
  3239.    double C = getClose(shift);
  3240.    double C1 = getClose(shift+1);
  3241.    double CL = H-L;
  3242.  
  3243.    double OC_HL;
  3244.    if((H - L) != 0) {
  3245.       OC_HL = (O-C)/(H-L);
  3246.    } else {
  3247.       OC_HL = 0;
  3248.    }
  3249.  
  3250.    double Piercing_Line_Ratio = 0.5;
  3251.    double Piercing_Candle_Length = 10;
  3252.  
  3253.    if ((C1>O1)&&(((C1+O1)/2)>C)&&(O>C)&&(C>O1)&&(OC_HL>Piercing_Line_Ratio)&&((CL>=Piercing_Candle_Length*sqGetPointCoef(symbol)))) {
  3254.       return(true);
  3255.    }
  3256.  
  3257.    return(false);
  3258. }
  3259.  
  3260. //+------------------------------------------------------------------+
  3261.  
  3262. bool sqDoji(string symbol, int shift) {
  3263.    if(MathAbs(getOpen(shift) - getClose(shift))*sqGetPointCoef(symbol) < 0.6) {
  3264.       return(true);
  3265.    }
  3266.    return(false);
  3267. }
  3268.  
  3269. //+------------------------------------------------------------------+
  3270.  
  3271. bool sqHammer(string symbol, int shift) {
  3272.    double H = getHigh(shift);
  3273.    double L = getLow(shift);
  3274.    double L1 = getLow(shift+1);
  3275.    double L2 = getLow(shift+2);
  3276.    double L3 = getLow(shift+3);
  3277.  
  3278.    double O = getOpen(shift);
  3279.    double C = getClose(shift);
  3280.    double CL = H-L;
  3281.  
  3282.    double BodyLow, BodyHigh;
  3283.    double Candle_WickBody_Percent = 0.9;
  3284.    double CandleLength = 12;
  3285.  
  3286.    if (O > C) {
  3287.       BodyHigh = O;
  3288.       BodyLow = C;
  3289.    } else {
  3290.       BodyHigh = C;
  3291.       BodyLow = O;
  3292.    }
  3293.  
  3294.    double LW = BodyLow-L;
  3295.    double UW = H-BodyHigh;
  3296.    double BLa = MathAbs(O-C);
  3297.    double BL90 = BLa*Candle_WickBody_Percent;
  3298.  
  3299.    double pipValue = sqGetPointCoef(symbol);
  3300.  
  3301.    if ((L<=L1)&&(L<L2)&&(L<L3))  {
  3302.       if (((LW/2)>UW)&&(LW>BL90)&&(CL>=(CandleLength*pipValue))&&(O!=C)&&((LW/3)<=UW)&&((LW/4)<=UW))  {
  3303.          return(true);
  3304.       }
  3305.       if (((LW/3)>UW)&&(LW>BL90)&&(CL>=(CandleLength*pipValue))&&(O!=C)&&((LW/4)<=UW))  {
  3306.          return(true);
  3307.       }
  3308.       if (((LW/4)>UW)&&(LW>BL90)&&(CL>=(CandleLength*pipValue))&&(O!=C))  {
  3309.          return(true);
  3310.       }
  3311.    }
  3312.  
  3313.    return(false);
  3314. }
  3315.  
  3316. //+------------------------------------------------------------------+
  3317.  
  3318. bool sqPiercingLine(string symbol, int shift) {
  3319.    double L = getLow(shift);
  3320.    double H = getHigh(shift);
  3321.  
  3322.    double O = getOpen(shift);
  3323.    double O1 = getOpen(shift+1);
  3324.    double C = getClose(shift);
  3325.    double C1 = getClose(shift+1);
  3326.    double CL = H-L;
  3327.  
  3328.    double CO_HL;
  3329.    if((H - L) != 0) {
  3330.       CO_HL = (C-O)/(H-L);
  3331.    } else {
  3332.       CO_HL = 0;
  3333.    }
  3334.  
  3335.    double Piercing_Line_Ratio = 0.5;
  3336.    double Piercing_Candle_Length = 10;
  3337.  
  3338.    if ((C1<O1)&&(((O1+C1)/2)<C)&&(O<C) && (CO_HL>Piercing_Line_Ratio)&&(CL>=(Piercing_Candle_Length*sqGetPointCoef(symbol)))) {
  3339.       return(true);
  3340.    }
  3341.  
  3342.    return(false);
  3343. }
  3344.  
  3345. //+------------------------------------------------------------------+
  3346.  
  3347. bool sqShootingStar(string symbol, int shift) {
  3348.    double L = getLow(shift);
  3349.    double H = getHigh(shift);
  3350.    double H1 = getHigh(shift+1);
  3351.    double H2 = getHigh(shift+2);
  3352.    double H3 = getHigh(shift+3);
  3353.  
  3354.    double O = getOpen(shift);
  3355.    double C = getClose(shift);
  3356.    double CL = H-L;
  3357.  
  3358.    double BodyLow, BodyHigh;
  3359.    double Candle_WickBody_Percent = 0.9;
  3360.    double CandleLength = 12;
  3361.  
  3362.    if (O > C) {
  3363.       BodyHigh = O;
  3364.       BodyLow = C;
  3365.    } else {
  3366.       BodyHigh = C;
  3367.       BodyLow = O;
  3368.    }
  3369.  
  3370.    double LW = BodyLow-L;
  3371.    double UW = H-BodyHigh;
  3372.    double BLa = MathAbs(O-C);
  3373.    double BL90 = BLa*Candle_WickBody_Percent;
  3374.  
  3375.    double pipValue = sqGetPointCoef(symbol);
  3376.  
  3377.    if ((H>=H1)&&(H>H2)&&(H>H3))  {
  3378.       if (((UW/2)>LW)&&(UW>(2*BL90))&&(CL>=(CandleLength*pipValue))&&(O!=C)&&((UW/3)<=LW)&&((UW/4)<=LW))  {
  3379.          return(true);
  3380.       }
  3381.       if (((UW/3)>LW)&&(UW>(2*BL90))&&(CL>=(CandleLength*pipValue))&&(O!=C)&&((UW/4)<=LW))  {
  3382.          return(true);
  3383.       }
  3384.       if (((UW/4)>LW)&&(UW>(2*BL90))&&(CL>=(CandleLength*pipValue))&&(O!=C))  {
  3385.          return(true);
  3386.       }
  3387.    }
  3388.  
  3389.    return(false);
  3390. }
  3391.  
  3392. //+------------------------------------------------------------------+
  3393. //| returns runtime error code description                           |
  3394. //+------------------------------------------------------------------+
  3395. string ErrorDescription(int err_code)
  3396.   {
  3397. //---
  3398.    switch(err_code)
  3399.      {
  3400.       //--- Constant Description
  3401.       case ERR_SUCCESS:                      return("The operation completed successfully");
  3402.       case ERR_INTERNAL_ERROR:               return("Unexpected internal error");
  3403.       case ERR_WRONG_INTERNAL_PARAMETER:     return("Wrong parameter in the inner call of the client terminal function");
  3404.       case ERR_INVALID_PARAMETER:            return("Wrong parameter when calling the system function");
  3405.       case ERR_NOT_ENOUGH_MEMORY:            return("Not enough memory to perform the system function");
  3406.       case ERR_STRUCT_WITHOBJECTS_ORCLASS:   return("The structure contains objects of strings and/or dynamic arrays and/or structure of such objects and/or classes");
  3407.       case ERR_INVALID_ARRAY:                return("Array of a wrong type, wrong size, or a damaged object of a dynamic array");
  3408.       case ERR_ARRAY_RESIZE_ERROR:           return("Not enough memory for the relocation of an array, or an attempt to change the size of a static array");
  3409.       case ERR_STRING_RESIZE_ERROR:          return("Not enough memory for the relocation of string");
  3410.       case ERR_NOTINITIALIZED_STRING:        return("Not initialized string");
  3411.       case ERR_INVALID_DATETIME:             return("Invalid date and/or time");
  3412.       case ERR_ARRAY_BAD_SIZE:               return("Requested array size exceeds 2 GB");
  3413.       case ERR_INVALID_POINTER:              return("Wrong pointer");
  3414.       case ERR_INVALID_POINTER_TYPE:         return("Wrong type of pointer");
  3415.       case ERR_FUNCTION_NOT_ALLOWED:         return("System function is not allowed to call");
  3416.       //--- Charts 
  3417.       case ERR_CHART_WRONG_ID:               return("Wrong chart ID");
  3418.       case ERR_CHART_NO_REPLY:               return("Chart does not respond");
  3419.       case ERR_CHART_NOT_FOUND:              return("Chart not found");
  3420.       case ERR_CHART_NO_EXPERT:              return("No Expert Advisor in the chart that could handle the event");
  3421.       case ERR_CHART_CANNOT_OPEN:            return("Chart opening error");
  3422.       case ERR_CHART_CANNOT_CHANGE:          return("Failed to change chart symbol and period");
  3423.       case ERR_CHART_WRONG_PARAMETER:        return("Wrong parameter");
  3424.       case ERR_CHART_CANNOT_CREATE_TIMER:    return("Failed to create timer");
  3425.       case ERR_CHART_WRONG_PROPERTY:         return("Wrong chart property ID");
  3426.       case ERR_CHART_SCREENSHOT_FAILED:      return("Error creating screenshots");
  3427.       case ERR_CHART_NAVIGATE_FAILED:        return("Error navigating through chart");
  3428.       case ERR_CHART_TEMPLATE_FAILED:        return("Error applying template");
  3429.       case ERR_CHART_WINDOW_NOT_FOUND:       return("Subwindow containing the indicator was not found");
  3430.       case ERR_CHART_INDICATOR_CANNOT_ADD:   return("Error adding an indicator to chart");
  3431.       case ERR_CHART_INDICATOR_CANNOT_DEL:   return("Error deleting an indicator from the chart");
  3432.       case ERR_CHART_INDICATOR_NOT_FOUND:    return("Indicator not found on the specified chart");
  3433.       //--- Graphical Objects  
  3434.       case ERR_OBJECT_ERROR:                 return("Error working with a graphical object");
  3435.       case ERR_OBJECT_NOT_FOUND:             return("Graphical object was not found");
  3436.       case ERR_OBJECT_WRONG_PROPERTY:        return("Wrong ID of a graphical object property");
  3437.       case ERR_OBJECT_GETDATE_FAILED:        return("Unable to get date corresponding to the value");
  3438.       case ERR_OBJECT_GETVALUE_FAILED:       return("Unable to get value corresponding to the date");
  3439.       //--- MarketInfo 
  3440.       case ERR_MARKET_UNKNOWN_SYMBOL:        return("Unknown symbol");
  3441.       case ERR_MARKET_NOT_SELECTED:          return("Symbol is not selected in MarketWatch");
  3442.       case ERR_MARKET_WRONG_PROPERTY:        return("Wrong identifier of a symbol property");
  3443.       case ERR_MARKET_LASTTIME_UNKNOWN:      return("Time of the last tick is not known (no ticks)");
  3444.       case ERR_MARKET_SELECT_ERROR:          return("Error adding or deleting a symbol in MarketWatch");
  3445.       //--- History Access 
  3446.       case ERR_HISTORY_NOT_FOUND:            return("Requested history not found");
  3447.       case ERR_HISTORY_WRONG_PROPERTY:       return("Wrong ID of the history property");
  3448.       //--- Global_Variables   
  3449.       case ERR_GLOBALVARIABLE_NOT_FOUND:     return("Global variable of the client terminal is not found");
  3450.       case ERR_GLOBALVARIABLE_EXISTS:        return("Global variable of the client terminal with the same name already exists");
  3451.       case ERR_MAIL_SEND_FAILED:             return("Email sending failed");
  3452.       case ERR_PLAY_SOUND_FAILED:            return("Sound playing failed");
  3453.       case ERR_MQL5_WRONG_PROPERTY:          return("Wrong identifier of the program property");
  3454.       case ERR_TERMINAL_WRONG_PROPERTY:      return("Wrong identifier of the terminal property");
  3455.       case ERR_FTP_SEND_FAILED:              return("File sending via ftp failed");
  3456.       case ERR_NOTIFICATION_SEND_FAILED:     return("Error in sending notification");
  3457.       //--- Custom Indicator Buffers
  3458.       case ERR_BUFFERS_NO_MEMORY:            return("Not enough memory for the distribution of indicator buffers");
  3459.       case ERR_BUFFERS_WRONG_INDEX:          return("Wrong indicator buffer index");
  3460.       //--- Custom Indicator Properties
  3461.       case ERR_CUSTOM_WRONG_PROPERTY:        return("Wrong ID of the custom indicator property");
  3462.       //--- Account
  3463.       case ERR_ACCOUNT_WRONG_PROPERTY:       return("Wrong account property ID");
  3464.       case ERR_TRADE_WRONG_PROPERTY:         return("Wrong trade property ID");
  3465.       case ERR_TRADE_DISABLED:               return("Trading by Expert Advisors prohibited");
  3466.       case ERR_TRADE_POSITION_NOT_FOUND:     return("Position not found");
  3467.       case ERR_TRADE_ORDER_NOT_FOUND:        return("Order not found");
  3468.       case ERR_TRADE_DEAL_NOT_FOUND:         return("Deal not found");
  3469.       case ERR_TRADE_SEND_FAILED:            return("Trade request sending failed");
  3470.       //--- Indicators 
  3471.       case ERR_INDICATOR_UNKNOWN_SYMBOL:     return("Unknown symbol");
  3472.       case ERR_INDICATOR_CANNOT_CREATE:      return("Indicator cannot be created");
  3473.       case ERR_INDICATOR_NO_MEMORY:          return("Not enough memory to add the indicator");
  3474.       case ERR_INDICATOR_CANNOT_APPLY:       return("The indicator cannot be applied to another indicator");
  3475.       case ERR_INDICATOR_CANNOT_ADD:         return("Error applying an indicator to chart");
  3476.       case ERR_INDICATOR_DATA_NOT_FOUND:     return("Requested data not found");
  3477.       case ERR_INDICATOR_WRONG_HANDLE:       return("Wrong indicator handle");
  3478.       case ERR_INDICATOR_WRONG_PARAMETERS:   return("Wrong number of parameters when creating an indicator");
  3479.       case ERR_INDICATOR_PARAMETERS_MISSING: return("No parameters when creating an indicator");
  3480.       case ERR_INDICATOR_CUSTOM_NAME:        return("The first parameter in the array must be the name of the custom indicator");
  3481.       case ERR_INDICATOR_PARAMETER_TYPE:     return("Invalid parameter type in the array when creating an indicator");
  3482.       case ERR_INDICATOR_WRONG_INDEX:        return("Wrong index of the requested indicator buffer");
  3483.       //--- Depth of Market
  3484.       case ERR_BOOKS_CANNOT_ADD:             return("Depth Of Market can not be added");
  3485.       case ERR_BOOKS_CANNOT_DELETE:          return("Depth Of Market can not be removed");
  3486.       case ERR_BOOKS_CANNOT_GET:             return("The data from Depth Of Market can not be obtained");
  3487.       case ERR_BOOKS_CANNOT_SUBSCRIBE:       return("Error in subscribing to receive new data from Depth Of Market");
  3488.       //--- File Operations
  3489.       case ERR_TOO_MANY_FILES:               return("More than 64 files cannot be opened at the same time");
  3490.       case ERR_WRONG_FILENAME:               return("Invalid file name");
  3491.       case ERR_TOO_LONG_FILENAME:            return("Too long file name");
  3492.       case ERR_CANNOT_OPEN_FILE:             return("File opening error");
  3493.       case ERR_FILE_CACHEBUFFER_ERROR:       return("Not enough memory for cache to read");
  3494.       case ERR_CANNOT_DELETE_FILE:           return("File deleting error");
  3495.       case ERR_INVALID_FILEHANDLE:           return("A file with this handle was closed, or was not opening at all");
  3496.       case ERR_WRONG_FILEHANDLE:             return("Wrong file handle");
  3497.       case ERR_FILE_NOTTOWRITE:              return("The file must be opened for writing");
  3498.       case ERR_FILE_NOTTOREAD:               return("The file must be opened for reading");
  3499.       case ERR_FILE_NOTBIN:                  return("The file must be opened as a binary one");
  3500.       case ERR_FILE_NOTTXT:                  return("The file must be opened as a text");
  3501.       case ERR_FILE_NOTTXTORCSV:             return("The file must be opened as a text or CSV");
  3502.       case ERR_FILE_NOTCSV:                  return("The file must be opened as CSV");
  3503.       case ERR_FILE_READERROR:               return("File reading error");
  3504.       case ERR_FILE_BINSTRINGSIZE:           return("String size must be specified, because the file is opened as binary");
  3505.       case ERR_INCOMPATIBLE_FILE:            return("A text file must be for string arrays, for other arrays - binary");
  3506.       case ERR_FILE_IS_DIRECTORY:            return("This is not a file, this is a directory");
  3507.       case ERR_FILE_NOT_EXIST:               return("File does not exist");
  3508.       case ERR_FILE_CANNOT_REWRITE:          return("File can not be rewritten");
  3509.       case ERR_WRONG_DIRECTORYNAME:          return("Wrong directory name");
  3510.       case ERR_DIRECTORY_NOT_EXIST:          return("Directory does not exist");
  3511.       case ERR_FILE_ISNOT_DIRECTORY:         return("This is a file, not a directory");
  3512.       case ERR_CANNOT_DELETE_DIRECTORY:      return("The directory cannot be removed");
  3513.       case ERR_CANNOT_CLEAN_DIRECTORY:       return("Failed to clear the directory (probably one or more files are blocked and removal operation failed)");
  3514.       case ERR_FILE_WRITEERROR:              return("Failed to write a resource to a file");
  3515.       //--- String Casting 
  3516.       case ERR_NO_STRING_DATE:               return("No date in the string");
  3517.       case ERR_WRONG_STRING_DATE:            return("Wrong date in the string");
  3518.       case ERR_WRONG_STRING_TIME:            return("Wrong time in the string");
  3519.       case ERR_STRING_TIME_ERROR:            return("Error converting string to date");
  3520.       case ERR_STRING_OUT_OF_MEMORY:         return("Not enough memory for the string");
  3521.       case ERR_STRING_SMALL_LEN:             return("The string length is less than expected");
  3522.       case ERR_STRING_TOO_BIGNUMBER:         return("Too large number, more than ULONG_MAX");
  3523.       case ERR_WRONG_FORMATSTRING:           return("Invalid format string");
  3524.       case ERR_TOO_MANY_FORMATTERS:          return("Amount of format specifiers more than the parameters");
  3525.       case ERR_TOO_MANY_PARAMETERS:          return("Amount of parameters more than the format specifiers");
  3526.       case ERR_WRONG_STRING_PARAMETER:       return("Damaged parameter of string type");
  3527.       case ERR_STRINGPOS_OUTOFRANGE:         return("Position outside the string");
  3528.       case ERR_STRING_ZEROADDED:             return("0 added to the string end, a useless operation");
  3529.       case ERR_STRING_UNKNOWNTYPE:           return("Unknown data type when converting to a string");
  3530.       case ERR_WRONG_STRING_OBJECT:          return("Damaged string object");
  3531.       //--- Operations with Arrays 
  3532.       case ERR_INCOMPATIBLE_ARRAYS:          return("Copying incompatible arrays. String array can be copied only to a string array, and a numeric array - in numeric array only");
  3533.       case ERR_SMALL_ASSERIES_ARRAY:         return("The receiving array is declared as AS_SERIES, and it is of insufficient size");
  3534.       case ERR_SMALL_ARRAY:                  return("Too small array, the starting position is outside the array");
  3535.       case ERR_ZEROSIZE_ARRAY:               return("An array of zero length");
  3536.       case ERR_NUMBER_ARRAYS_ONLY:           return("Must be a numeric array");
  3537.       case ERR_ONEDIM_ARRAYS_ONLY:           return("Must be a one-dimensional array");
  3538.       case ERR_SERIES_ARRAY:                 return("Timeseries cannot be used");
  3539.       case ERR_DOUBLE_ARRAY_ONLY:            return("Must be an array of type double");
  3540.       case ERR_FLOAT_ARRAY_ONLY:             return("Must be an array of type float");
  3541.       case ERR_LONG_ARRAY_ONLY:              return("Must be an array of type long");
  3542.       case ERR_INT_ARRAY_ONLY:               return("Must be an array of type int");
  3543.       case ERR_SHORT_ARRAY_ONLY:             return("Must be an array of type short");
  3544.       case ERR_CHAR_ARRAY_ONLY:              return("Must be an array of type char");
  3545.       //--- Operations with OpenCL 
  3546.       case ERR_OPENCL_NOT_SUPPORTED:         return("OpenCL functions are not supported on this computer");
  3547.       case ERR_OPENCL_INTERNAL:              return("Internal error occurred when running OpenCL");
  3548.       case ERR_OPENCL_INVALID_HANDLE:        return("Invalid OpenCL handle");
  3549.       case ERR_OPENCL_CONTEXT_CREATE:        return("Error creating the OpenCL context");
  3550.       case ERR_OPENCL_QUEUE_CREATE:          return("Failed to create a run queue in OpenCL");
  3551.       case ERR_OPENCL_PROGRAM_CREATE:        return("Error occurred when compiling an OpenCL program");
  3552.       case ERR_OPENCL_TOO_LONG_KERNEL_NAME:  return("Too long kernel name (OpenCL kernel)");
  3553.       case ERR_OPENCL_KERNEL_CREATE:         return("Error creating an OpenCL kernel");
  3554.       case ERR_OPENCL_SET_KERNEL_PARAMETER:  return("Error occurred when setting parameters for the OpenCL kernel");
  3555.       case ERR_OPENCL_EXECUTE:               return("OpenCL program runtime error");
  3556.       case ERR_OPENCL_WRONG_BUFFER_SIZE:     return("Invalid size of the OpenCL buffer");
  3557.       case ERR_OPENCL_WRONG_BUFFER_OFFSET:   return("Invalid offset in the OpenCL buffer");
  3558.       case ERR_OPENCL_BUFFER_CREATE:         return("Failed to create and OpenCL buffer");
  3559.       //--- User-Defined Errors
  3560.       default: if(err_code>=ERR_USER_ERROR_FIRST && err_code<ERR_USER_ERROR_LAST)
  3561.                                              return("User error "+string(err_code-ERR_USER_ERROR_FIRST));
  3562.      }
  3563. //---
  3564.    return("Unknown error");
  3565.   }
  3566.  
  3567. //+------------------------------------------------------------------+
  3568.  
  3569. double getATR(string symbol, int timeframe, int ma_period, int shift){
  3570.    string atrSymbol = correctSymbol(symbol);
  3571.    ENUM_TIMEFRAMES atrTimeframe = (timeframe == NULL || timeframe == 0) ? _Period : TFMigrate(timeframe);
  3572.  
  3573.    int handle = iATR(atrSymbol, atrTimeframe, ma_period);
  3574.    
  3575.    return(sqGetIndicatorValue(handle, 0, shift));
  3576. }
  3577.  
  3578. //+------------------------------------------------------------------+
  3579.  
  3580. //+------------------------------------------------------------------+
  3581. //+------------------------------------------------------------------+
  3582. // ExitMethods includes
  3583. //+------------------------------------------------------------------+
  3584. //+------------------------------------------------------------------+
  3585.  
  3586.  
  3587. void sqSetSLPT(long ticket, double sl, double pt){
  3588.    ZeroMemory(mrequest);
  3589.    
  3590.    if(PositionSelectByTicket(ticket)) {
  3591.       mrequest.position = ticket;
  3592.       mrequest.action = TRADE_ACTION_SLTP;
  3593.       mrequest.sl = sl != 0 ? sl : PositionGetDouble(POSITION_SL);
  3594.       mrequest.tp = pt != 0 ? pt : PositionGetDouble(POSITION_TP);
  3595.    }
  3596.    else if(OrderSelect(ticket)){
  3597.       mrequest.order = ticket;
  3598.       mrequest.action = TRADE_ACTION_MODIFY;
  3599.       mrequest.price = OrderGetDouble(ORDER_PRICE_OPEN);
  3600.       mrequest.sl = sl != 0 ? sl : OrderGetDouble(ORDER_SL);
  3601.       mrequest.tp = pt != 0 ? pt : OrderGetDouble(ORDER_TP);
  3602.    }
  3603.    else {
  3604.       Print(StringFormat("No order or position with ticket %d not found", ticket));
  3605.    }
  3606.    
  3607.    //--- setting request
  3608.    mrequest.symbol = PositionGetString(POSITION_SYMBOL);
  3609.    mrequest.magic = PositionGetInteger(POSITION_MAGIC);
  3610.    
  3611.    //--- action and return the result
  3612.    OrderSend(mrequest,mresult);
  3613. }
  3614. // Move Stop Loss to Break Even
  3615. void sqManageSL2BE(int ticket) {
  3616.  
  3617.    if(!PositionSelectByTicket(ticket)){
  3618.        Verbose("Cannot select position with ticket ", ticket);
  3619.        return;
  3620.    }
  3621.                                                                          
  3622.    valueIdentificationSymbol = PositionGetString(POSITION_SYMBOL);
  3623.    double moveSLAtValue = sqGetValueByIdentification( sqGetMoveSL2BE(ticket) );
  3624.  
  3625.    if(moveSLAtValue > 0) {
  3626.       double newSL = 0;
  3627.       int error;
  3628.  
  3629.       int valueType = sqGetMoveSL2BEType(ticket);
  3630.       int orderType = PositionGetInteger(POSITION_TYPE);
  3631.  
  3632.       if(orderType == ORDER_TYPE_BUY || orderType == ORDER_TYPE_BUY_STOP || orderType == ORDER_TYPE_BUY_LIMIT) {
  3633.          if(valueType == SLPTTYPE_RANGE) {
  3634.             moveSLAtValue = sqGetBid(NULL) - moveSLAtValue;
  3635.          }
  3636.       } else {
  3637.          if(valueType == SLPTTYPE_RANGE) {
  3638.             moveSLAtValue = sqGetAsk(NULL) + moveSLAtValue;
  3639.          }
  3640.       }
  3641.      
  3642.       moveSLAtValue = NormalizeDouble(moveSLAtValue, _Digits);
  3643.  
  3644.       double addPips = sqGetValueByIdentification(sqGetSL2BEAddPips(ticket));
  3645.       double currentSL = PositionGetDouble(POSITION_SL);
  3646.       double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
  3647.       double takeProfit = PositionGetDouble(POSITION_TP);
  3648.  
  3649.       if(orderType == ORDER_TYPE_BUY) {
  3650.          newSL = openPrice + addPips;
  3651.          if (openPrice <= moveSLAtValue && (currentSL == 0 || currentSL < newSL) && !sqDoublesAreEqual(currentSL, newSL)) {
  3652.             Verbose("Moving SL 2 BE for order with ticket: ", ticket, " to :", newSL);
  3653.             if(!OrderModify(ticket, newSL, takeProfit)) {
  3654.                error = GetLastError();
  3655.                Verbose("Failed, error: ", error, " - ", ErrorDescription(error),", Ask: ", sqGetAsk(NULL), ", Bid: ", sqGetBid(NULL), " Current SL: ",  currentSL);
  3656.             }
  3657.          }
  3658.  
  3659.       } else { // orderType == OP_SELL
  3660.          newSL = openPrice - addPips;
  3661.          if (openPrice >= moveSLAtValue && (currentSL == 0 || currentSL > newSL) && !sqDoublesAreEqual(currentSL, newSL)) {
  3662.             Verbose("Moving SL 2 BE for order with ticket: ", ticket, "  to :", newSL);
  3663.             if(!OrderModify(ticket, newSL, takeProfit)) {
  3664.                error = GetLastError();
  3665.                Verbose("Failed, error: ", error, " - ", ErrorDescription(error),", Ask: ", sqGetAsk(NULL), ", Bid: ", sqGetBid(NULL), " Current SL: ",  currentSL);
  3666.             }
  3667.          }
  3668.       }
  3669.    }
  3670. }
  3671. // Trailing Stop
  3672. void sqManageTrailingStop(int ticket) {
  3673.    if(!PositionSelectByTicket(ticket)){
  3674.        Verbose("Cannot select position with ticket ", ticket);
  3675.        return;
  3676.    }
  3677.                                                                                            
  3678.    valueIdentificationSymbol = PositionGetString(POSITION_SYMBOL);
  3679.    double tsValue = sqGetValueByIdentification( sqGetTrailingStop(ticket) );
  3680.    if(tsValue > 0) {
  3681.       double plValue;
  3682.       int error;
  3683.  
  3684.       int valueType = sqGetTrailingStopType(ticket);
  3685.       int orderType = PositionGetInteger(POSITION_TYPE);
  3686.  
  3687.       if(orderType == POSITION_TYPE_BUY) {
  3688.          if(valueType == SLPTTYPE_RANGE) {
  3689.             tsValue = sqGetBid(NULL) - tsValue;
  3690.          }
  3691.       } else {
  3692.          if(valueType == SLPTTYPE_RANGE) {
  3693.             tsValue = sqGetAsk(NULL) + tsValue;
  3694.          }
  3695.       }
  3696.  
  3697.       double tsActivation = sqGetValueByIdentification( sqGetTSActivation(ticket) );
  3698.       double currentSL = PositionGetDouble(POSITION_SL);      
  3699.       double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
  3700.       double takeProfit = PositionGetDouble(POSITION_TP);
  3701.  
  3702.       if(orderType == POSITION_TYPE_BUY) {
  3703.          plValue = sqGetBid(NULL) - openPrice;
  3704.  
  3705.          if (plValue >= tsActivation && (currentSL == 0 || currentSL < tsValue) && !sqDoublesAreEqual(currentSL, tsValue)) {
  3706.             Verbose("Moving trailing stop for order with ticket: ", ticket, " to :", tsValue);
  3707.             if(!OrderModify(ticket, tsValue, takeProfit)) {
  3708.                error = GetLastError();
  3709.                Verbose("Failed, error: ", error, " - ", ErrorDescription(error),", Ask: ", sqGetAsk(NULL), ", Bid: ", sqGetBid(NULL), " Current SL: ",  currentSL);
  3710.             }
  3711.          }
  3712.       } else { // orderType == OP_SELL
  3713.          plValue = openPrice - sqGetAsk(NULL);
  3714.  
  3715.          if (plValue >= tsActivation && (currentSL == 0 || currentSL > tsValue) && !sqDoublesAreEqual(currentSL, tsValue)) {
  3716.             Verbose("Moving trailing stop for order with ticket: ", ticket, " to :", tsValue);
  3717.             if(!OrderModify(ticket, tsValue, takeProfit)) {
  3718.                error = GetLastError();
  3719.                Verbose("Failed, error: ", error, " - ", ErrorDescription(error),", Ask: ", sqGetAsk(NULL), ", Bid: ", sqGetBid(NULL), " Current SL: ",  currentSL);
  3720.             }
  3721.          }
  3722.       }
  3723.    }
  3724. }
  3725. void sqManageExitAfterXBars(int ticket) {
  3726.    if(!PositionSelectByTicket(ticket)){
  3727.        Verbose("Exit after bars - Cannot select position with ticket ", ticket);
  3728.        return;
  3729.    }
  3730.  
  3731.    int exitBars = sqGetExitAfterXBars(ticket);
  3732.    if(exitBars > 0) {
  3733.       if (sqGetOpenBarsForOrder(exitBars+10, PositionGetInteger(POSITION_TIME)) >= exitBars) {
  3734.          Verbose("Exit After ", exitBars, " bars - closing order with ticket: ", ticket);
  3735.          if(!sqClosePositionAtMarket(ticket)){
  3736.             Verbose("Closing position failed, error: ", GetLastError(), " - ", ErrorDescription(GetLastError()));
  3737.          }
  3738.       }
  3739.    }
  3740. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement