//+------------------------------------------------------------------+ //| Ea2.mq5 | //| Copyright 2025, Niquel Mendoza. | //| https://www.mql5.com/es/users/nique_372/news | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, Niquel Mendoza." #property link "https://www.mql5.com/es/users/nique_372/news" #property version "1.00" #property strict #property tester_indicator "OrderBlockIndPart2.ex5" #resource "\\Shared Projects\\MQLArticles\\Ob\\Indicator\\OrderBlockIndPart2.ex5" //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum ENUM_TP_SL_STYLE { ATR = 0, //Atr POINT = 1 //Points }; //+------------------------------------------------------------------+ //| Include | //+------------------------------------------------------------------+ // To avoid unnecessary copying of the RSI data, we will define the define CONDITIONAL_PARTIAL_EXECUTE_WHEN_THE_ARE_POSITIONS // This implies that the execution of Execute is only done when there are positions to review. #define CONDITIONAL_PARTIAL_EXECUTE_WHEN_THE_ARE_POSITIONS #define CONDITIONALPARTIAL_FACTORY_MQH #define CONDITIONALPARTIAL_CONDITION_SIMPLE_RSI_MQH #include "..\\..\\..\\PosMgmt\\ConditionalPartial\\Main.mqh" #include "..\\..\\..\\PosMgmt\\Breakeven.mqh" //+------------------------------------------------------------------+ //| Inputs | //+------------------------------------------------------------------+ sinput group "-------| General |-------" input ulong InpMagic = 545244; //Magic number sinput group "-------| Ob Indicator settings |-------" input ENUM_TIMEFRAMES InpObTimeframe = PERIOD_M5; //Order block timeframe input int InpObRangoUniversalBusqueda = 500; //search range of order blocks input int InpObWidth = 1; //Width order block input bool InpObBack = true; //Back order block? input bool InpObFill = true; //Fill order block? input color InpObColorBajista = clrRed; //Bearish order block color input color InpObColorAlcista = clrGreen; //Bullish order block color input double InpObTransparency = 0.5; // Transparency from 0.0 (invisible) to 1.0 (opaque) sinput group "" sinput group "-------| Strategy |-------" input ENUM_TP_SL_STYLE InpStrtTpSlStyle = ATR;//Tp and sl style: sinput group "- TP SL by ATR " input double InpStrtAtrMultiplier1 = 9.3;//Atr multiplier 1 (SL) input double InpStrtAtrMultiplier2 = 24.4;//Atr multiplier 2 (TP) sinput group "- TP SL by POINT " input int InpStrtTpPoint = 1000; //TP in Points input int InpStrtSlPoint = 1000; //SL in Points sinput group "" sinput group "-------| Account Status |-------" input ENUM_VERBOSE_LOG_LEVEL InpLogLevelAccountStatus = VERBOSE_LOG_LEVEL_ERROR_ONLY; //(Account Status|Ticket Mangement) log level: sinput group "" sinput group "-------| Risk Management |-------" input ENUM_LOTE_TYPE InpRmLoteType = Dinamico; //Lote Type: input double InpRmLote = 0.1; //Lot size (only for fixed lot) input ENUM_MODE_RISK_MANAGEMENT InpRmRiskMode = risk_mode_personal_account; //type of g_risk management mode input ENUM_GET_LOT InpRmGetMode = GET_LOT_BY_STOPLOSS_AND_RISK_PER_OPERATION; //How to get the lot input double InpRmPropFirmBalance = 0; //If g_risk mode is Prop Firm FTMO, then put your ftmo account balance input ENUM_VERBOSE_LOG_LEVEL InpRmLogLevel = VERBOSE_LOG_LEVEL_ERROR_ONLY; //Risk Management log level: sinput group "- ML/Maximum loss/Maximum loss -" input double InpRmPercentageOrMoneyMl = 0; //percentage or money (0 => not used ML) input ENUM_RISK_CALCULATION_MODE InpRmModeCalculationMl = percentage; //Mode calculation Max Loss input ENUM_APPLIED_PERCENTAGES InpRmAppliedPercentagesMl = Balance; //ML percentage applies to: sinput group "- MWL/Maximum weekly loss/Maximum weekly loss -" input double InpRmPercentageOrMoneyMwl = 0; //percentage or money (0 => not used MWL) input ENUM_RISK_CALCULATION_MODE InpRmModeCalculationMwl = percentage; //Mode calculation Max weekly Loss input ENUM_APPLIED_PERCENTAGES InpRmAppliedPercentagesMwl = Balance;//MWL percentage applies to: sinput group "- MDL/Maximum daily loss/Maximum daily loss -" input double InpRmPercentageOrMoneyMdl = 3.0; //percentage or money (0 => not used MDL) input ENUM_RISK_CALCULATION_MODE InpRmModeCalculationMdl = percentage; //Mode calculation Max daily loss input ENUM_APPLIED_PERCENTAGES InpRmAppliedPercentagesMdl = Balance;//MDL percentage applies to: sinput group "- GMLPO/Gross maximum loss per operation/Percentage to g_risk per operation -" input ENUM_OF_DYNAMIC_MODES_OF_GMLPO InpRmModeGmlpo = NO_DYNAMIC_GMLPO; //Select GMLPO mode: input double InpRmPercentageOrMoneyGmlpo = 2.0; //percentage or money (0 => not used GMLPO) input ENUM_RISK_CALCULATION_MODE InpRmModeCalculationGmlpo = percentage; //Mode calculation Max Loss per operation input ENUM_APPLIED_PERCENTAGES InpRmAppliedPercentagesGmlpo = Balance;//GMPLO percentage applies to: sinput group "-- Optional GMLPO settings, Dynamic GMLPO" sinput group "--- Full customizable dynamic GMLPO" input string InpRmNote1 = "subtracted from your total balance to establish a threshold."; //This parameter determines a specific percentage that will be input string InpRmStrPercentagesToBeReviewed = "15,30,50"; //percentages separated by commas. input string InpRmNote2 = "a new g_risk level will be triggered on your future trades: "; //When the current balance (equity) falls below this threshold input string InpRmStrPercentagesToApply = "10,20,25"; //percentages separated by commas. input string InpRmNote3 = "0 in both parameters => do not use dynamic g_risk in gmlpo"; //Note: sinput group "--- Fixed dynamic GMLPO with parameters" sinput group "- 1 -" input string InpRmNote11 = "subtracted from your total balance to establish a threshold."; //This parameter determines a specific percentage that will be input double InpRmBalancePercentageToActivateTheRisk1 = 2.0; //percentage 1 that will be exceeded to modify the g_risk separated by commas input string InpRmNote21 = "a new g_risk level will be triggered on your future trades: "; //When the current balance (equity) falls below this threshold input double InpRmPercentageToBeModified1 = 1.0;//new percentage 1 to which the gmlpo is modified sinput group "- 2 -" input double InpRmBalancePercentageToActivateTheRisk2 = 5.0;//percentage 2 that will be exceeded to modify the g_risk separated by commas input double InpRmPercentageToBeModified2 = 0.7;//new percentage 2 to which the gmlpo is modified sinput group "- 3 -" input double InpRmBalancePercentageToActivateTheRisk3 = 7.0;//percentage 3 that will be exceeded to modify the g_risk separated by commas input double InpRmPercentageToBeModified3 = 0.5;//new percentage 3 to which the gmlpo is modified sinput group "- 4 -" input double InpRmBalancePercentageToActivateTheRisk4 = 9.0;//percentage 4 that will be exceeded to modify the g_risk separated by commas input double InpRmPercentageToBeModified4 = 0.33;//new percentage 4 1 to which the gmlpo is modified sinput group "-- MDP/Maximum daily profit/Maximum daily profit --" input bool InpRmMdpIsStrict = true; //MDP is strict? input double InpRmPercentageOrMoneyMdp = 11.0; //percentage or money (0 => not used MDP) input ENUM_RISK_CALCULATION_MODE InpRmModeCalculationMdp = percentage; //Mode calculation Max Daily Profit input ENUM_APPLIED_PERCENTAGES InpRmAppliedPercentagesMdp = Balance;//MDP percentage applies to: sinput group "" sinput group "-------| Risk Modifier 1 |-------" input bool InpRmod1Enable = false; // Enables dynamic g_risk adjustment (Booster) input double InpRmod1Step = 2.0; // Increment applied to g_risk each time the condition is met input double InpRmod1Start = 2.0; // Profit percentage from which g_risk adjustment begins input ENUM_MULTIPLIER_METHOD_DR InpRmod1Method = DR_EXPONECIAL; // Type of progression used to increase g_risk sinput group "" sinput group "-------| Risk modifier 2 |-------" input bool InpRmod2Enable = false; //Activate g_risk modifier 2 input string InpRmod2StrPercentagesToApply = "6, 8, 10, 20, 25"; //Percentages to apply sinput group "" sinput group "-------| Risk modifier 3 by Kevin |-------" input bool InpRmod3Enable = false; //Activate g_risk modifier 3 input double InpRmod3Constant = 8.0; //Function constant sinput group "" sinput group "-------| Session |-------" input char InpSessionStartHour = 1; // Start hour to operate (0-23) input char InpSessionStartMinute = 0; // Start minute to operate (0-59) input char InpSessionEndHour = 23; // End hour to operate (1-23) input char InpSessionEndMinute = 0; // End minute to operate (0-59) sinput group "" sinput group "-------| Breakeven |-------" input bool InpBeUse = false; // Enable Breakeven logic input ENUM_BREAKEVEN_TYPE InpBeType = BREAKEVEN_TYPE_RR; // Calculation method (RR, ATR, or fixed points) input ENUM_VERBOSE_LOG_LEVEL InpBeLogLevel = VERBOSE_LOG_LEVEL_ERROR_ONLY; // Break Even log level: //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ sinput group "--- Breakeven based on Risk/Reward (RR) ---" input string InpBeRrAdv = "Requires a configured Stop Loss."; // Warning: Stop Loss is required to calculate RR input double InpBeRrRatio = 1.0; // Risk/Reward ratio to activate Breakeven (e.g. 1.0) input ENUM_TYPE_EXTRA_BE_BY_RRR InpBeRrTypeExtra = EXTRA_BE_RRR_BY_ATR;// Method to adjust Breakeven price (ATR or points) input double InpBeRrExtraPointsOrAtrMultiplier = 1.0; // Adjustment value: ATR multiplier (atr 14 period) if method = ATR, or fixed points if method = Points sinput group "--- Breakeven based solely on ATR ---" input double InpBeAtrMultiplier = 2.0; // ATR multiplier to trigger Breakeven (atr 14 period) input double InpBeAtrMultiplierExtra = 1.0; // Additional multiplier for precise Breakeven adjustment (atr 14 period) sinput group "--- Breakeven based on fixed points ---" input int InpBeFixedPointsToPutBe = 200; // Minimum distance (in points) to trigger Breakeven input int InpBeFixedPointsExtra = 100; // Extra points added when Breakeven is triggered sinput group "" sinput group "-------| Partial Closures by Rsi condition |-------" input ENUM_VERBOSE_LOG_LEVEL InpPartialsLogLevel = VERBOSE_LOG_LEVEL_ERROR_ONLY; // Partial Closures log level input bool InpPartialsIsEnable = true; // Enable partials ? input ENUM_TYPE_CONDITIONAL_PARTIAL_CLASS InpPartialsClassManagerType = CONDITIONAL_PARTIAL_CLASS_TYPE_BASE; // Partial class manager type: input double InpPartialsVolumeToClosePercentage = 20.0; // Volume to close input ENUM_TIMEFRAMES InpPartialsRsiTimeframe = PERIOD_CURRENT; // Rsi timeframe input int InpPartialsRsiPeriod = 14; // Rsi period input double InpPartialsRsiOverBoughtLevel = 70.0; // Rsi overbought level input double InpPartialsRsiOverSoldLevel = 30.0; // Rsi oversold level input double InpPartialsMinDistanceInAtrMul = 1.0; // Min distance between partials in atr14 mult //+------------------------------------------------------------------+ //| Global variables | //+------------------------------------------------------------------+ CTrade g_trade; CRiskManagemet* g_risk; CBreakEven g_break_even(InpMagic, _Symbol); CConditionalPartials* g_partials; CAtr* g_atr; //--- Handles int order_block_indicator_handle; int ma_handle; //--- Global buffers double tp1[]; double tp2[]; double sl1[]; double sl2[]; //--- Session datetime start_sesion; datetime end_sesion; //--- General CBarControlerFast bar_d1(PERIOD_D1, _Symbol); CBarControlerFast bar_w1(PERIOD_W1, _Symbol); CBarControlerFast bar_mn1(PERIOD_MN1, _Symbol); CBarControlerFast bar_curr(PERIOD_CURRENT, _Symbol); CDynamicRisk riesgo_c(InpRmod1Step, InpRmod1Start, LP_GMLPO, InpRmod1Method); CModifierDynamicRisk risk_modificator(InpRmod2StrPercentagesToApply); CMathDynamicRisk risk_modificator_kevin(InpRmod3Constant); //--- bool CanTrade = true; CAtrUltraOptimized atr_ultra_optimized; const CLossProfitManager* g_loss_profit_manager; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Atr atr_ultra_optimized.SetVariables(_Period, _Symbol, 0, 14); atr_ultra_optimized.SetInternalPointer(); //--- We set the breakeven values so its use is allowed if(InpBeUse) { g_break_even.SetBeByAtr(InpBeAtrMultiplier, InpBeAtrMultiplierExtra, GetPointer(atr_ultra_optimized)); g_break_even.SetBeByFixedPoints(InpBeFixedPointsToPutBe, InpBeFixedPointsExtra); g_break_even.SetBeByRR(InpBeRrRatio, InpBeRrTypeExtra, InpBeRrExtraPointsOrAtrMultiplier, GetPointer(atr_ultra_optimized)); g_break_even.SetInternalPointer(InpBeType); g_break_even.obj.AddLogFlags(InpBeLogLevel); } //--- Partials if(InpPartialsIsEnable) { // Atr creation g_atr = new CAtr(); g_atr.Create(_Period, _Symbol, 14, true, true); g_atr.SetAsSeries(true); // We assign to g_partilas the dynamic instance returned by CConditionalPartialsFactory::Create(...) g_partials = CConditionalPartialsFactory::Create(InpPartialsClassManagerType); // Initial log flags g_partials.AddLogFlags(InpPartialsLogLevel); // Create condition CConditionalPartialsIndRsi* rsi_condition = new CConditionalPartialsIndRsi(); // Rsi condition config if(!rsi_condition.Init(InpPartialsRsiTimeframe, _Symbol, InpPartialsRsiPeriod, InpPartialsRsiOverBoughtLevel, InpPartialsRsiOverSoldLevel)) return INIT_PARAMETERS_INCORRECT; // Condition config ConditionalPartialConfig config; config.condition = rsi_condition; config.min_distance_to_close_pos = CreateDiffptr(MODE_DIFF_BY_ATR, _Symbol, g_atr, 0, InpPartialsMinDistanceInAtrMul); config.str_percentage_volume_to_close = DoubleToString(InpPartialsVolumeToClosePercentage, 4); config.magic_number = InpMagic; // Init partials if(g_partials.Init(config)) { account_status.AddItemFast(g_partials); // Add to account status } else // Error in parameters return INIT_PARAMETERS_INCORRECT; if(InpPartialsClassManagerType == CONDITIONAL_PARTIAL_CLASS_TYPE_CONSTANT) { CConditionalPartialsConst* partial = (CConditionalPartialsConst*)g_partials; partial.ForzeToClose(true); } } //--- Indicators // Create ob handle order_block_indicator_handle = CreateIndicatorObHandle(); // Create ma handle ma_handle = iMA(_Symbol, InpObTimeframe, 30, 0, MODE_EMA, PRICE_CLOSE); // Check ma if(ma_handle == INVALID_HANDLE) { Print("The ema indicator is not available latest error: ", _LastError); return INIT_FAILED; } ChartIndicatorAdd(0, 0, ma_handle); //--- Trade g_trade.SetExpertMagicNumber(InpMagic); //--- Risk management CRiskPointer* manager = new CRiskPointer(InpMagic, InpRmGetMode); manager.SetPropirm(InpRmPropFirmBalance); g_risk = manager.GetRiskPointer(InpRmRiskMode); g_risk.AddLogFlags(InpRmLogLevel); g_risk.SetLote(CreateLotePtr(_Symbol)); // We set the parameters string to_apply = InpRmStrPercentagesToApply, to_modfied = InpRmStrPercentagesToBeReviewed; if(InpRmModeGmlpo == DYNAMIC_GMLPO_FIXED_PARAMETERS) SetDynamicUsingFixedParameters(InpRmBalancePercentageToActivateTheRisk1, InpRmBalancePercentageToActivateTheRisk2, InpRmBalancePercentageToActivateTheRisk3 , InpRmBalancePercentageToActivateTheRisk4, InpRmPercentageToBeModified1, InpRmPercentageToBeModified2, InpRmPercentageToBeModified3, InpRmPercentageToBeModified4 , to_modfied, to_apply); g_risk.AddLoss(InpRmPercentageOrMoneyMdl, InpRmAppliedPercentagesMdl, InpRmModeCalculationMdl, LP_MDL, true); g_risk.AddLoss(InpRmPercentageOrMoneyGmlpo, InpRmAppliedPercentagesGmlpo, InpRmModeCalculationGmlpo, LP_GMLPO, true, (InpRmModeGmlpo != NO_DYNAMIC_GMLPO), to_modfied, to_apply); g_risk.AddLoss(InpRmPercentageOrMoneyMl, InpRmAppliedPercentagesMl, InpRmModeCalculationMl, LP_ML, true); g_risk.AddLoss(InpRmPercentageOrMoneyMwl, InpRmAppliedPercentagesMwl, InpRmModeCalculationMwl, LP_MWL, true); g_risk.AddProfit(InpRmPercentageOrMoneyMdp, InpRmAppliedPercentagesMdp, InpRmModeCalculationMdp, LP_MDP, InpRmMdpIsStrict); g_risk.EndAddProfitLoss(); // Execute this every time we finish setting the maximum losses and profits g_loss_profit_manager = g_risk.GetLossProfitManager(); // We add modifiers if(InpRmod1Enable) g_risk.AddModificator(riesgo_c); if(InpRmod2Enable) g_risk.AddModificator(risk_modificator); if(InpRmod3Enable) g_risk.AddModificator(risk_modificator_kevin); // We finish by adding it account_status.AddItemFast(g_risk); // We delete the temporary pointer delete manager; //--- We initialize the account account_status.AddLogFlagTicket(InpLogLevelAccountStatus); account_status.AddLogFlags(InpLogLevelAccountStatus); account_status.OnInitEvent(); //--- We configure the arrays in series ArraySetAsSeries(tp1, true); ArraySetAsSeries(tp2, true); ArraySetAsSeries(sl1, true); ArraySetAsSeries(sl2, true); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- Indicators ChartIndicatorDelete(0, 0, ChartIndicatorName(0, 0, GetMovingAverageIndex())); ChartIndicatorDelete(0, 0, "Order Block Indicator"); if(ma_handle != INVALID_HANDLE) IndicatorRelease(ma_handle); if(order_block_indicator_handle != INVALID_HANDLE) IndicatorRelease(order_block_indicator_handle); //--- Partials if(InpPartialsIsEnable) { delete g_atr; } } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- General const datetime time_curr = TimeCurrent(); //--- Code that runs every new day if(bar_d1.IsNewBar(time_curr)) { account_status.OnNewDay(); if(bar_w1.IsNewBar(time_curr)) account_status.OnNewWeek(); if(bar_mn1.IsNewBar(time_curr)) account_status.OnNewMonth(); CanTrade = true; } //--- if(account_status_positions_open) { CAccountStatus_OnTickEvent if(CanTrade) { if(g_loss_profit_manager.MaxLossIsSuperated()) { const ENUM_TYPE_LOSS_PROFIT type = g_loss_profit_manager.GetLastLossSuperatedType(); if(type == LP_ML) { if(InpRmRiskMode == risk_mode_propfirm_dynamic_daiy_loss) { Print("The expert advisor lost the funding test"); } else { Print("Maximum loss exceeded now"); } //--- Remover(); } else if(type == LP_MDL) { Print("Maximum daily loss exceeded now"); } //--- g_risk.CloseAllPositions(); CanTrade = false; } else if(g_loss_profit_manager.MaxProfitIsSuperated()) { if(g_loss_profit_manager.GetLastProfitSuperatedType() != LP_MDP) return; g_risk.CloseAllPositions(); Print("Excellent Maximum daily profit achieved"); CanTrade = false; } } } //--- Check Session if(time_curr > end_sesion) { start_sesion = HoraYMinutoADatetime(InpSessionStartHour, InpSessionStartMinute, time_curr); end_sesion = HoraYMinutoADatetime(InpSessionEndHour, InpSessionEndMinute, time_curr); if(start_sesion > end_sesion) end_sesion = end_sesion + 86400; } //--- Breakeven if(InpBeUse) g_break_even.obj.BreakEven(); //--- bar controlation const bool new_bar = bar_curr.IsNewBar(time_curr); //--- Partials if(InpPartialsIsEnable && new_bar) { g_atr.CopyData(0, 1); // Copy atr data g_partials.Execute(time_curr); // Execution in newbar } //--- Check to operate if(!CanTrade) return; //--- Strategy if(new_bar) { if(time_curr > start_sesion && time_curr < end_sesion) { if(g_risk.GetPositionsTotal() == 0) { CopyBuffer(order_block_indicator_handle, 2, 0, 5, tp1); CopyBuffer(order_block_indicator_handle, 3, 0, 5, tp2); CopyBuffer(order_block_indicator_handle, 4, 0, 5, sl1); CopyBuffer(order_block_indicator_handle, 5, 0, 5, sl2); if(tp1[0] > 0 && tp2[0] > 0 && sl1[0] > 0 && sl2[0] > 0) { if(tp2[0] > sl2[0]) // buy orders { const double ASK = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits); g_risk.SetStopLoss(ASK - sl1[0]); const double lot = (InpRmLoteType == Dinamico ? g_risk.GetLote(ORDER_TYPE_BUY, ASK, 0, 0) : InpRmLote); g_trade.Buy(lot, _Symbol, ASK, sl1[0], tp2[0], "Order Block EA Buy"); } else if(sl2[0] > tp2[0]) // sell orders { const double BID = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits); g_risk.SetStopLoss(sl1[0] - BID); const double lot = (InpRmLoteType == Dinamico ? g_risk.GetLote(ORDER_TYPE_SELL, BID, 0, 0) : InpRmLote); g_trade.Sell(lot, _Symbol, BID, sl1[0], tp2[0], "Order Block EA Sell"); } } } } } } //+------------------------------------------------------------------+ //| TradeTransaction function | //+------------------------------------------------------------------+ void OnTradeTransaction(const MqlTradeTransaction & trans, const MqlTradeRequest & request, const MqlTradeResult & result) { account_status.OnTradeTransactionEvent(trans); } //+------------------------------------------------------------------+ //| Extra Functions | //+------------------------------------------------------------------+ int GetMovingAverageIndex(long chart_id = 0) { int total_indicators = ChartIndicatorsTotal(chart_id, 0); for(int i = 0; i < total_indicators; i++) { string indicator_name = ChartIndicatorName(chart_id, 0, i); if(StringFind(indicator_name, "MA") >= 0) return i; } return -1; } //+------------------------------------------------------------------+ int CreateIndicatorObHandle() { //--- We configure the indicator parameters MqlParam param[19]; param[0].type = TYPE_STRING; param[0].string_value = "::Shared Projects\\MQLArticles\\Ob\\Indicator\\OrderBlockIndPart2.ex5"; param[1].type = TYPE_STRING; param[1].string_value = "--- Order Block Indicator settings ---"; param[2].type = TYPE_BOOL; param[2].integer_value = false; param[3].type = TYPE_STRING; param[3].string_value = "-- Order Block --"; param[4].type = TYPE_INT; param[4].integer_value = InpObRangoUniversalBusqueda; param[5].type = TYPE_INT; param[5].integer_value = InpObWidth; param[6].type = TYPE_BOOL; param[6].integer_value = InpObBack; param[7].type = TYPE_BOOL; param[7].integer_value = InpObFill; param[8].type = TYPE_COLOR; param[8].integer_value = InpObColorBajista; param[9].type = TYPE_COLOR; param[9].integer_value = InpObColorAlcista; param[10].type = TYPE_DOUBLE; param[10].double_value = InpObTransparency; param[11].type = TYPE_STRING; param[11].string_value = "-- Strategy --"; param[12].type = TYPE_INT; param[12].integer_value = InpStrtTpSlStyle; param[13].type = TYPE_STRING; param[13].string_value = "- ATR"; param[14].type = TYPE_DOUBLE; param[14].double_value = InpStrtAtrMultiplier1; param[15].type = TYPE_DOUBLE; param[15].double_value = InpStrtAtrMultiplier2; param[16].type = TYPE_STRING; param[16].string_value = "- POINT"; param[17].type = TYPE_INT; param[17].integer_value = InpStrtTpPoint; param[18].type = TYPE_INT; param[18].integer_value = InpStrtSlPoint; order_block_indicator_handle = IndicatorCreate(_Symbol, InpObTimeframe, IND_CUSTOM, ArraySize(param), param); if(order_block_indicator_handle == INVALID_HANDLE) { Print("The order blocks indicator is not available last error: ", _LastError); ExpertRemove(); return INVALID_HANDLE; } ChartIndicatorAdd(0, 0, order_block_indicator_handle); return order_block_indicator_handle; } //+------------------------------------------------------------------+