1191 lines
46 KiB
MQL5
1191 lines
46 KiB
MQL5
//+------------------------------------------------------------------+
| |||
//| OrderBlockIndPart2.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"
| |||
| |||
#define Version "2.01"
| |||
#property version Version
| |||
#property indicator_chart_window
| |||
#property strict
| |||
| |||
#property indicator_buffers 6
| |||
#property indicator_plots 6
| |||
| |||
#property indicator_label1 "Buy"
| |||
#property indicator_type1 DRAW_ARROW
| |||
#property indicator_color1 clrGreen
| |||
#property indicator_width1 1
| |||
| |||
#property indicator_label2 "Sell"
| |||
#property indicator_type2 DRAW_ARROW
| |||
#property indicator_color2 clrRed
| |||
#property indicator_width2 1
| |||
| |||
#property indicator_label3 "Take Profit 1"
| |||
#property indicator_label4 "Take Profit 2"
| |||
#property indicator_label5 "Stop Loss 1"
| |||
#property indicator_label6 "Stop Loss 2"
| |||
| |||
| |||
enum ENUM_TP_SL_STYLE
| |||
{
| |||
ATR = 0, //Atr
| |||
POINT = 1 //Points
| |||
};
| |||
| |||
| |||
#include "Main.mqh"
| |||
| |||
sinput group "--- Order Block Indicator settings ---"
| |||
input bool enable_alerts = true; //Enable alerts ?
| |||
| |||
sinput group "-- Order Block --"
| |||
input int Universal_range_search = 500; //Range to find order blocks
| |||
input int Witdth_order_block = 1; //Order Blocks Width
| |||
input bool Back_order_block = true; //Background for the rectangles of the order blocks?
| |||
input bool Fill_order_block = true; //Fill order block?
| |||
input color Color_Order_Block_Bajista = clrRed; //Bullish order block color
| |||
input color Color_Order_Block_Alcista = clrGreen; //Bearish order block color
| |||
input double transparecy = 0.3 ;//Transparency 0 - 1.0 (1.0 opaque and 0.0 transparent)
| |||
| |||
sinput group "-- Strategy --"
| |||
input ENUM_TP_SL_STYLE tp_sl_style = POINT; //Type of TP and SL:
| |||
| |||
sinput group " ATR "
| |||
input double Atr_Multiplier_1 = 1.5; //Atr multiplier 1 for the tp and sl
| |||
input double Atr_Multiplier_2 = 2.0; //Atr multiplier 2 for the tp and sl
| |||
| |||
sinput group " POINT "
| |||
input int TP_POINT = 500; //Takeprofit in points
| |||
input int SL_POINT = 275; //Stoploss in points
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Structures and Global Variables |
| |||
//+------------------------------------------------------------------+
| |||
struct OrderBlocks
| |||
{
| |||
datetime time1;
| |||
datetime time2;
| |||
double price1;
| |||
double price2;
| |||
string name;
| |||
bool mitigated;
| |||
bool case_book;
| |||
};
| |||
| |||
//--- Order Blocks Array
| |||
OrderBlocks bearish_ob[];
| |||
OrderBlocks bullish_ob[];
| |||
string pricetwo_eliminados_oba[];
| |||
string pricetwo_eliminados_obb[];
| |||
| |||
//--- Buffers
| |||
double buy_buffer[];
| |||
double sell_buffer[];
| |||
double tp1_buffer[];
| |||
double tp2_buffer[];
| |||
double sl1_buffer[];
| |||
double sl2_buffer[];
| |||
| |||
//--- Extra variables
| |||
datetime last_candle_time;
| |||
double ma[];
| |||
double atr[];
| |||
| |||
//--- Arrays longs para almacenar el volumen del book
| |||
long buy_volume[];
| |||
long sell_volume[];
| |||
| |||
//--- Flag to mark if the maket_book is used
| |||
bool use_market_book = true;
| |||
| |||
//--- Indicators handles
| |||
int Rsi_Handle; //Rsi handle
| |||
int hanlde_ma; //Ma Handle
| |||
int atr_i; //Atr Handle
| |||
| |||
//--- prefix for objects (this is to avoid conflicts with other order block indicators, or objects with the same name)
| |||
string code_obj;
| |||
| |||
//--- Extra
| |||
color color_of_bullish_ob;
| |||
color color_of_bearish_ob;
| |||
#define ORDER_BLOCK_IND_NAME "OrderBlockIndicator"
| |||
//+------------------------------------------------------------------+
| |||
//| Custom indicator initialization function |
| |||
//+------------------------------------------------------------------+
| |||
int OnInit()
| |||
{
| |||
//---
| |||
MathSrand(GetTickCount());
| |||
code_obj = StringFormat("%s_%s_%d_ob_indicator_",_Symbol,Version,MathRand());
| |||
//---
| |||
color_of_bullish_ob = ApplyTransparency(Color_Order_Block_Alcista, transparecy);
| |||
color_of_bearish_ob = ApplyTransparency(Color_Order_Block_Bajista, transparecy);
| |||
| |||
//---
| |||
if(Universal_range_search < 40)
| |||
{
| |||
ob_logger.LogError(StringFormat("Very small search range = %d", Universal_range_search), ORDER_BLOCK_IND_NAME);
| |||
return (INIT_PARAMETERS_INCORRECT);
| |||
}
| |||
| |||
//---
| |||
if(Universal_range_search >= Bars(_Symbol, _Period) + 31)
| |||
{
| |||
ob_logger.LogError(StringFormat("The data available for the indicator calculations are less than the calculation range %d", Bars(_Symbol, _Period) + 20, Universal_range_search), ORDER_BLOCK_IND_NAME);
| |||
return (INIT_PARAMETERS_INCORRECT);
| |||
}
| |||
| |||
//---
| |||
int max_attempts = 1000; // Maximum attempts (500 x 10ms = 5 seconds)
| |||
while(!SeriesInfoInteger(_Symbol, PERIOD_CURRENT, SERIES_SYNCHRONIZED) && max_attempts-- > 0)
| |||
Sleep(10);
| |||
| |||
if(max_attempts <= 1)
| |||
{
| |||
ob_logger.LogError("The data required for the indicator to function correctly is not synchronized.", ORDER_BLOCK_IND_NAME);
| |||
return INIT_FAILED;
| |||
}
| |||
| |||
datetime dummy[];
| |||
CopyTime(_Symbol, _Period, 0, MathMax(Bars(_Symbol, _Period) - 10, 100), dummy);
| |||
Sleep(100);
| |||
| |||
//--- Atr
| |||
ResetLastError();
| |||
atr_i = iATR(_Symbol, PERIOD_CURRENT, 14);
| |||
if(atr_i == INVALID_HANDLE)
| |||
{
| |||
ob_logger.LogError(StringFormat("The atr handle is invalid, last error descripcion: %s", ErrorDescription(GetLastError())), ORDER_BLOCK_IND_NAME);
| |||
return(INIT_FAILED);
| |||
}
| |||
| |||
//--- Ma
| |||
ResetLastError();
| |||
hanlde_ma = iMA(_Symbol, _Period, 30, 0, MODE_EMA, PRICE_CLOSE);
| |||
if(hanlde_ma == INVALID_HANDLE)
| |||
{
| |||
ob_logger.LogError(StringFormat("The ema indicator is not available. last error descripcion: %s", ErrorDescription(GetLastError())), ORDER_BLOCK_IND_NAME);
| |||
return(INIT_FAILED);
| |||
}
| |||
| |||
//--- Market Book
| |||
ResetLastError();
| |||
if(!MarketBookAdd(_Symbol))
| |||
{
| |||
use_market_book = false;
| |||
ob_logger.LogError(StringFormat("The order book could not be opened. last error descripcion: %s", ErrorDescription(GetLastError())), ORDER_BLOCK_IND_NAME);
| |||
}
| |||
else
| |||
ob_logger.LogInfo(StringFormat("Market Book available for the symbol: %s", _Symbol), ORDER_BLOCK_IND_NAME);
| |||
| |||
//---
| |||
ArrayResize(bearish_ob, 0);
| |||
ArrayResize(bullish_ob, 0);
| |||
ArraySetAsSeries(ma, true);
| |||
ArraySetAsSeries(atr, true);
| |||
string short_name = StringFormat("Order Block Indicator[%d]", Universal_range_search);
| |||
IndicatorSetString(INDICATOR_SHORTNAME, short_name);
| |||
IndicatorSetInteger(INDICATOR_DIGITS, _Digits);
| |||
| |||
//--- Plots
| |||
PlotIndexSetString(0, PLOT_LABEL, "Buy");
| |||
PlotIndexSetInteger(0, PLOT_ARROW, 233);
| |||
| |||
PlotIndexSetString(1, PLOT_LABEL, "Sell");
| |||
PlotIndexSetInteger(1, PLOT_ARROW, 234);
| |||
| |||
PlotIndexSetString(2, PLOT_LABEL, "Take Profit 1");
| |||
PlotIndexSetString(3, PLOT_LABEL, "Take Profit 2");
| |||
PlotIndexSetString(4, PLOT_LABEL, "Stop Loss 1");
| |||
PlotIndexSetString(5, PLOT_LABEL, "Stop Loss 2");
| |||
| |||
//--- Buffers
| |||
SetIndexBuffer(0, buy_buffer, INDICATOR_DATA);
| |||
SetIndexBuffer(1, sell_buffer, INDICATOR_DATA);
| |||
SetIndexBuffer(2, tp1_buffer, INDICATOR_DATA);
| |||
SetIndexBuffer(3, tp2_buffer, INDICATOR_DATA);
| |||
SetIndexBuffer(4, sl1_buffer, INDICATOR_DATA);
| |||
SetIndexBuffer(5, sl2_buffer, INDICATOR_DATA);
| |||
| |||
//---
| |||
ArraySetAsSeries(buy_buffer, true);
| |||
ArraySetAsSeries(sell_buffer, true);
| |||
ArrayFill(buy_buffer, 0, 0, EMPTY_VALUE);
| |||
ArrayFill(sell_buffer, 0, 0, EMPTY_VALUE);
| |||
| |||
//---
| |||
ArraySetAsSeries(tp1_buffer, true);
| |||
ArraySetAsSeries(tp2_buffer, true);
| |||
ArrayFill(tp1_buffer, 0, 0, EMPTY_VALUE);
| |||
ArrayFill(tp2_buffer, 0, 0, EMPTY_VALUE);
| |||
| |||
//---
| |||
ArraySetAsSeries(sl1_buffer, true);
| |||
ArraySetAsSeries(sl2_buffer, true);
| |||
ArrayFill(sl1_buffer, 0, 0, EMPTY_VALUE);
| |||
ArrayFill(sl2_buffer, 0, 0, EMPTY_VALUE);
| |||
| |||
//---
| |||
ArrayResize(buy_volume, 1);
| |||
ArrayResize(sell_volume, 1);
| |||
| |||
//---
| |||
buy_volume[0] = 0.0;
| |||
sell_volume[0] = 0.0;
| |||
| |||
//---
| |||
return(INIT_SUCCEEDED);
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Custom indicator iteration function |
| |||
//+------------------------------------------------------------------+
| |||
int OnCalculate(const int rates_total,
| |||
const int prev_calculated,
| |||
const datetime &time[],
| |||
const double &open[],
| |||
const double &high[],
| |||
const double &low[],
| |||
const double &close[],
| |||
const long &tick_volume[],
| |||
const long &volume[],
| |||
const int &spread[])
| |||
{
| |||
//---
| |||
static int counter = 0;
| |||
| |||
if(rates_total > prev_calculated)
| |||
{
| |||
counter++;
| |||
if(last_candle_time != iTime(_Symbol, PERIOD_D1, 0))
| |||
{
| |||
Eliminar_Objetos();
| |||
ArrayFree(bearish_ob);
| |||
ArrayFree(bullish_ob);
| |||
last_candle_time = iTime(_Symbol, PERIOD_D1, 0);
| |||
}
| |||
| |||
if(counter > 1 && use_market_book == true)
| |||
{
| |||
if(ArraySize(buy_volume) > 4 && ArraySize(sell_volume) > 4)
| |||
{
| |||
if(buy_volume[3] == 0 && sell_volume[3] == 0 &&
| |||
buy_volume[2] == 0 && sell_volume[2] == 0 &&
| |||
buy_volume[1] == 0 && sell_volume[1] == 0)
| |||
{
| |||
use_market_book = false;
| |||
ob_logger.LogWarning("Disabling use of the market book because there is no data available.", ORDER_BLOCK_IND_NAME);
| |||
}
| |||
}
| |||
| |||
if(ArraySize(buy_volume) >= 30)
| |||
{
| |||
ArrayResize(buy_volume, 30); // Ensure that the size of buy_volume does not exceed 30
| |||
ArrayResize(sell_volume, 30); // Ensure that the size of sell_volume does not exceed 30
| |||
}
| |||
| |||
ArrayResize(buy_volume, ArraySize(buy_volume) + 1);
| |||
ArrayResize(sell_volume, ArraySize(sell_volume) + 1);
| |||
| |||
for(int i = ArraySize(buy_volume) - 1; i > 0; i--)
| |||
{
| |||
buy_volume[i] = buy_volume[i - 1];
| |||
sell_volume[i] = sell_volume[i - 1];
| |||
}
| |||
| |||
buy_volume[0] = 0;
| |||
sell_volume[0] = 0;
| |||
}
| |||
}
| |||
| |||
//---
| |||
if(rates_total > prev_calculated)
| |||
{
| |||
ArraySetAsSeries(open, true);
| |||
ArraySetAsSeries(close, true);
| |||
ArraySetAsSeries(high, true);
| |||
ArraySetAsSeries(low, true);
| |||
ArraySetAsSeries(time, true);
| |||
ArraySetAsSeries(tick_volume, true);
| |||
| |||
if(prev_calculated == 0)
| |||
{
| |||
ResetLastError();
| |||
if(CopyBuffer(atr_i, 0, 0, Universal_range_search + 10, atr) < 1)
| |||
{
| |||
ob_logger.LogError(StringFormat("Could not copy data from the ATR indicator, last error description: %s", ErrorDescription(GetLastError())), ORDER_BLOCK_IND_NAME);
| |||
return rates_total;
| |||
}
| |||
| |||
ResetLastError();
| |||
if(CopyBuffer(hanlde_ma, 0, 0, 5, ma) < 5)
| |||
{
| |||
ob_logger.LogError(StringFormat("Could not copy data from the Ma indicator, last error description: %s", ErrorDescription(GetLastError())), ORDER_BLOCK_IND_NAME);
| |||
return rates_total;
| |||
}
| |||
}
| |||
else
| |||
{
| |||
ResetLastError();
| |||
if(CopyBuffer(atr_i, 0, 0, 10, atr) < 10)
| |||
{
| |||
ob_logger.LogError(StringFormat("Could not copy data from the ATR indicator, last error description: %s", ErrorDescription(GetLastError())), ORDER_BLOCK_IND_NAME);
| |||
return rates_total;
| |||
}
| |||
| |||
ResetLastError();
| |||
if(CopyBuffer(hanlde_ma, 0, 0, 5, ma) < 5)
| |||
{
| |||
ob_logger.LogError(StringFormat("Could not copy data from the Ma indicator, last error description: %s", ErrorDescription(GetLastError())), ORDER_BLOCK_IND_NAME);
| |||
return rates_total;
| |||
}
| |||
}
| |||
| |||
| |||
//----------------- Bullish order blocks
| |||
OrderBlocks newVela_Order_block_alcista;
| |||
OrderBlocks newVela_Order_block_volumen;
| |||
OrderBlocks newVela_Order_block_Book;
| |||
| |||
int inicio = prev_calculated == 0 ? Universal_range_search : 6;
| |||
| |||
for(int i = inicio ; i > 5 ; i--)
| |||
{
| |||
if(i + 3 > ArraySize(high) || i + 3 > ArraySize(atr))
| |||
continue;
| |||
if(i < 0)
| |||
continue;
| |||
| |||
//--- Declaracion de variables
| |||
int one_vela = i ;
| |||
int two_candles_previous_to_one_candle = i + 2;
| |||
int one_candle_before_one_candle = one_vela + 1;
| |||
int two_vela = one_vela - 1;
| |||
int tree_vela = one_vela - 2;
| |||
int four_vela = one_vela - 3;
| |||
double body1 = close[one_vela] - open[one_vela];
| |||
double body2 = close[two_vela] - open[two_vela];
| |||
double body3 = close[tree_vela] - open[two_vela];
| |||
long Volumen_one_vela = tick_volume[one_vela];
| |||
long Volumen_two_vela = tick_volume[two_vela];
| |||
long volumen_one_candle_before_one_candle = tick_volume[one_candle_before_one_candle];
| |||
| |||
bool case_bullish_orderblock_normal = false; //Flag indicating that the order block has been obtained in the "normal" case
| |||
bool case_orderblock_vol = false; //Flag indicating that the order block has been obtained by the "volume" case
| |||
| |||
//--- Conditions
| |||
bool IsCorrectCandleForNormalCase = close[one_vela] > open[one_vela] && close[two_vela] > open[two_vela]
| |||
&& close[tree_vela] > open[tree_vela] && close[four_vela] > open[four_vela];
| |||
| |||
bool IsHammerCandle = open[one_vela] - low[one_vela] > close[one_vela] - open[one_vela];
| |||
| |||
bool fuerte_movimiento_alcista = close[one_vela + 2] > open[one_vela + 2] &&
| |||
close[one_vela + 1] > open[one_vela + 1] &&
| |||
close[one_vela] > open[one_vela] &&
| |||
close[two_vela] > open[two_vela] &&
| |||
close[tree_vela] > open[tree_vela] &&
| |||
close[four_vela] > open[four_vela];
| |||
| |||
bool atr_case = atr[two_candles_previous_to_one_candle] > atr[one_vela] && atr[two_vela] > atr[one_vela] && atr[two_vela] > atr[two_candles_previous_to_one_candle] && close[one_vela] > open[one_vela]
| |||
&& close[four_vela] > open[four_vela] && close[tree_vela] > open[tree_vela]; //case by atr (included in normal)
| |||
| |||
| |||
if((IsCorrectCandleForNormalCase && ((low[two_vela] > ((body1 * 0.5) + open[one_vela]) && ((body2 * 0.4) + open[two_vela]) > high[one_vela]) || IsHammerCandle)
| |||
&& low[tree_vela] > ((body2 * 0.25) + open[two_vela])) || fuerte_movimiento_alcista || atr_case ) //Here at the beginning we look for the highlights not to exceed important points
| |||
{
| |||
int furthestAlcista = FindFurthestAlcista(time[one_vela], 20, _Period, _Symbol);
| |||
| |||
if(furthestAlcista > 0)
| |||
{
| |||
datetime time1 = time[furthestAlcista];
| |||
double price2 = open[furthestAlcista];
| |||
double price1 = low[furthestAlcista];
| |||
newVela_Order_block_alcista.price1 = price1;
| |||
newVela_Order_block_alcista.time1 = time1;
| |||
newVela_Order_block_alcista.price2 = price2;
| |||
newVela_Order_block_alcista.case_book = false;
| |||
case_bullish_orderblock_normal = true;
| |||
}
| |||
else
| |||
case_bullish_orderblock_normal = false;
| |||
}
| |||
| |||
//--- Verify that the case is met by volume
| |||
bool CorrectCandleForVolumeCase = close[one_vela] > open[one_vela] && close[two_vela] > open[two_vela];
| |||
bool CorrectVolume = Volumen_one_vela > Volumen_two_vela && Volumen_one_vela > volumen_one_candle_before_one_candle;
| |||
bool case_vol_2 = (tick_volume[one_vela] > volumen_one_candle_before_one_candle && tick_volume[two_vela] > tick_volume[one_vela] &&
| |||
open[tree_vela] < close[tree_vela] && open[four_vela] < close[four_vela]);
| |||
| |||
//---
| |||
if((CorrectVolume && CorrectCandleForVolumeCase
| |||
&& ((low[two_vela] > ((body1 * 0.5) + open[one_vela]) && ((body2 * 0.6) + open[two_vela]) > high[one_vela]) || IsHammerCandle == true)
| |||
&& high[tree_vela] > open[two_vela]) || case_vol_2 == true)
| |||
{
| |||
int furthestAlcista = FindFurthestAlcista(time[one_vela], 20, _Period, _Symbol);
| |||
if(furthestAlcista > 0)
| |||
{
| |||
datetime time1 = time[furthestAlcista];
| |||
double price2 = open[furthestAlcista];
| |||
double price1 = low[furthestAlcista];
| |||
newVela_Order_block_volumen.price1 = price1;
| |||
newVela_Order_block_volumen.time1 = time1;
| |||
newVela_Order_block_volumen.case_book = false;
| |||
newVela_Order_block_volumen.price2 = price2;
| |||
case_orderblock_vol = true;
| |||
}
| |||
else
| |||
case_orderblock_vol = false;
| |||
}
| |||
| |||
if(case_bullish_orderblock_normal && IsBullishObMitigated(newVela_Order_block_alcista.price2, low, time, newVela_Order_block_alcista.time1, time[0]) == 0)
| |||
{
| |||
newVela_Order_block_alcista.mitigated = false;
| |||
newVela_Order_block_alcista.name = code_obj + "bull_" + TimeToString(newVela_Order_block_alcista.time1) ;
| |||
AddArray(bullish_ob, newVela_Order_block_alcista);
| |||
}
| |||
if(case_orderblock_vol && IsBullishObMitigated(newVela_Order_block_volumen.price2, low, time, newVela_Order_block_volumen.time1, time[0]) == 0)
| |||
{
| |||
newVela_Order_block_volumen.mitigated = false;
| |||
newVela_Order_block_volumen.name = code_obj + "bull_" + TimeToString(newVela_Order_block_volumen.time1) ;
| |||
AddArray(bullish_ob, newVela_Order_block_volumen);
| |||
}
| |||
}
| |||
| |||
//--- Check the case on MarketBook
| |||
if(ArraySize(buy_volume) >= 5 && ArraySize(sell_volume) >= 5 && use_market_book)
| |||
{
| |||
const double ratio = 1.4;
| |||
bool case_book = buy_volume[3] > buy_volume[4] * ratio && buy_volume[3] > buy_volume[2] * ratio &&
| |||
buy_volume[3] > sell_volume[4] * ratio && buy_volume[3] > sell_volume[2] * ratio;
| |||
| |||
double body_tree = close[3] - open[3];
| |||
| |||
if(low[2] > ((body_tree * 0.5) + open[3]) && high[3] < close[2] &&
| |||
close[3] > open[3] && close[2] > open[2] && close[1] > open[1] && case_book)
| |||
{
| |||
int furthestAlcista = FindFurthestAlcista(time[3], 20, _Period, _Symbol);
| |||
if(furthestAlcista > 0)
| |||
{
| |||
datetime time1 = time[furthestAlcista];
| |||
double price2 = open[furthestAlcista];
| |||
double price1 = low[furthestAlcista];
| |||
newVela_Order_block_Book.price1 = price1;
| |||
newVela_Order_block_Book.time1 = time1;
| |||
newVela_Order_block_Book.price2 = price2;
| |||
newVela_Order_block_Book.case_book = true;
| |||
newVela_Order_block_Book.mitigated = false;
| |||
newVela_Order_block_Book.name = code_obj + "bull_" + TimeToString(newVela_Order_block_Book.time1);
| |||
AddArray(bullish_ob, newVela_Order_block_Book);
| |||
}
| |||
}
| |||
}
| |||
| |||
//---
| |||
static bool buscar_oba = true;
| |||
static datetime time_a = 0;
| |||
string curr_elimiandor_oba[];
| |||
| |||
for(int i = 0; i < ArraySize(bullish_ob); i++)
| |||
{
| |||
datetime mitigadoTime = IsBullishOrderBlockMitigated(bullish_ob[i], bullish_ob[i].time1);
| |||
| |||
if(!bullish_ob[i].mitigated)
| |||
{
| |||
if(ObjectFind(ChartID(), bullish_ob[i].name) < 0)
| |||
{
| |||
| |||
const static string tools[2] = { "Order Block Alcista", "Order Block Alcista Book" };
| |||
RectangleCreate(ChartID(), bullish_ob[i].name, 0, bullish_ob[i].time1, bullish_ob[i].price1,
| |||
time[0], bullish_ob[i].price2, color_of_bullish_ob, Witdth_order_block, Fill_order_block, Back_order_block, STYLE_SOLID, false, tools[int(bullish_ob[i].case_book)]);
| |||
}
| |||
else
| |||
ObjectSetInteger(ChartID(), bullish_ob[i].name, OBJPROP_TIME, 1, time[0]); //On the contrary, if the object exists, all we will do is update it at the current time using anchor point 1
| |||
}
| |||
else
| |||
{
| |||
if(enable_alerts)
| |||
Alert("The bullish order block is being mitigated: ", TimeToString(bullish_ob[i].time1));
| |||
| |||
AddArrayNoVerification(pricetwo_eliminados_oba, bullish_ob[i].name);
| |||
AddArrayNoVerification(curr_elimiandor_oba, bullish_ob[i].name);
| |||
| |||
if(buscar_oba == true)
| |||
{
| |||
buscar_oba = false;
| |||
time_a = iTime(_Symbol, _Period, 1);
| |||
}
| |||
| |||
}
| |||
}
| |||
| |||
for(int i = 0; i < ArraySize(curr_elimiandor_oba) ; i++)
| |||
DeleteArrayBiName(bullish_ob, curr_elimiandor_oba[i]);
| |||
| |||
if(buscar_oba == false && time_a > 0)
| |||
{
| |||
double close_ = NormalizeDouble(close[1], _Digits);
| |||
datetime max_time_espera = time_a + (PeriodSeconds() * 7); //Maximum wait 7 candles to confirm the break of the moving average
| |||
if(close_ > ma[1] && time[0] <= max_time_espera)
| |||
{
| |||
double ask = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits);
| |||
double tp1;
| |||
double tp2;
| |||
double sl1;
| |||
double sl2;
| |||
GetTP_SL(ask, POSITION_TYPE_BUY, tp1, tp2, sl1, sl2);
| |||
DrawTP_SL(tp1, tp2, sl1, sl2);
| |||
tp1_buffer[0] = tp1;
| |||
tp2_buffer[0] = tp2;
| |||
sl1_buffer[0] = sl1;
| |||
sl2_buffer[0] = sl2;
| |||
buy_buffer[0] = ask - atr[0] * 1.3;
| |||
time_a = 0;
| |||
buscar_oba = true;
| |||
}
| |||
if(time[0] > max_time_espera)
| |||
{
| |||
time_a = 0;
| |||
buscar_oba = true;
| |||
}
| |||
}
| |||
| |||
//----------------- Bearish order blocks
| |||
OrderBlocks newVela_Order_Block_bajista;
| |||
OrderBlocks newVela_Order_Block_bajista_2;
| |||
OrderBlocks newVela_Order_block_Book_bajista;
| |||
| |||
for(int i = inicio ; i > 5 ; i--)
| |||
{
| |||
if(i + 3 > ArraySize(high) || i + 3 > ArraySize(atr))
| |||
continue;
| |||
| |||
if(i < 0)
| |||
continue;
| |||
| |||
//-------- Variable Declaration --------------------------------------------//
| |||
// Update candlestick indices
| |||
int one_vela = i ; //vela central
| |||
int one_candle_before_one_candle = one_vela + 1;
| |||
int two_vela = one_vela - 1;
| |||
int tree_vela = one_vela - 2;
| |||
int two_candles_previous_to_one_candle = one_vela + 2;
| |||
double body1 = open[one_vela] - close[one_vela];
| |||
double body2 = open[two_vela] - close[two_vela];
| |||
double body3 = open[tree_vela] - close[tree_vela];
| |||
long Volumen_one_vela = tick_volume[one_vela];
| |||
long Volumen_two_vela = tick_volume[two_vela];
| |||
long volumen_one_candle_before_one_candle = tick_volume[one_candle_before_one_candle];
| |||
bool case_OrderBlockBajista_normal = false;
| |||
bool case_OrderBlockBajista_volumen = false;
| |||
| |||
bool IsCorrectCandleForNormalCase = close[one_vela] < open[one_vela] &&
| |||
close[two_vela] < open[two_vela] &&
| |||
close[tree_vela] < open[tree_vela] &&
| |||
close[one_vela - 3] < open[one_vela - 3];
| |||
| |||
bool a = atr[two_candles_previous_to_one_candle] > atr[one_vela] && atr[two_vela] > atr[one_vela] && atr[two_vela] > atr[two_candles_previous_to_one_candle] && IsCorrectCandleForNormalCase;
| |||
| |||
| |||
bool StrongBearishMovement = close[one_vela + 2] < open[one_vela + 2] && close[one_vela + 1] < open[one_vela + 1] && close[one_vela] < open[one_vela] &&
| |||
close[two_vela] < open[two_vela] && close[tree_vela] < open[tree_vela] && close[one_vela - 3] <= open[one_vela - 3];
| |||
| |||
if((IsCorrectCandleForNormalCase == true && high[two_vela] < ((body1 * 0.70) + close[one_vela]) && ((body2 * 0.4) + close[two_vela]) < low[one_vela] && high[tree_vela] < high[two_vela])
| |||
|| a || StrongBearishMovement)
| |||
{
| |||
int furthestBajista = FindFurthestBajista(time[one_vela], 20, _Period, _Symbol);
| |||
if(furthestBajista != -1)
| |||
{
| |||
datetime time1 = time[furthestBajista];
| |||
double price1 = close[furthestBajista];
| |||
double price2 = low[furthestBajista];
| |||
newVela_Order_Block_bajista.price1 = price1;
| |||
newVela_Order_Block_bajista.time1 = time1;
| |||
newVela_Order_Block_bajista.case_book = false;
| |||
newVela_Order_Block_bajista.price2 = price2 ;
| |||
}
| |||
else
| |||
case_OrderBlockBajista_normal = false;
| |||
}
| |||
| |||
bool CorrectCandleForVolumeCase = close[one_vela] < open[one_vela] && close[two_vela] < open[two_vela];
| |||
bool CorrectVolume = Volumen_one_vela > Volumen_two_vela && Volumen_one_vela > volumen_one_candle_before_one_candle;
| |||
bool case_vol_2 = tick_volume[one_vela] > volumen_one_candle_before_one_candle && tick_volume[two_vela] > tick_volume[one_vela] && open[tree_vela] > close[tree_vela] && open[one_vela - 3] > close[one_vela - 3];
| |||
| |||
if((CorrectVolume == true && CorrectCandleForVolumeCase == true && high[two_vela] < ((body1 * 0.5) + close[one_vela])
| |||
&& ((body2 * 0.5) + close[two_vela]) < low[one_vela]) || case_vol_2 == true) // verificamos si se cumple
| |||
{
| |||
int furthestBajista = FindFurthestBajista(time[one_vela], 20, _Period, _Symbol);
| |||
if(furthestBajista > 0)
| |||
{
| |||
datetime time1 = time[furthestBajista];
| |||
double price1 = close[furthestBajista];
| |||
double price2 = low[furthestBajista];
| |||
newVela_Order_Block_bajista_2.price1 = price1;
| |||
newVela_Order_Block_bajista_2.time1 = time1;
| |||
newVela_Order_Block_bajista_2.price2 = price2 ;
| |||
newVela_Order_Block_bajista_2.case_book = false;
| |||
case_OrderBlockBajista_volumen = true;
| |||
}
| |||
else
| |||
case_OrderBlockBajista_volumen = false;
| |||
}
| |||
| |||
if(case_OrderBlockBajista_normal == true && mitigado_bajista(newVela_Order_Block_bajista.price2, high, time, newVela_Order_Block_bajista.time1, time[0]) == 0)
| |||
{
| |||
newVela_Order_Block_bajista.mitigated = false;
| |||
newVela_Order_Block_bajista.name = code_obj + "bear_" + TimeToString(newVela_Order_Block_bajista.time1);
| |||
AddArray(bearish_ob, newVela_Order_Block_bajista); //we add the structure to the array
| |||
}
| |||
if(case_OrderBlockBajista_volumen == true && mitigado_bajista(newVela_Order_Block_bajista_2.price2, high, time, newVela_Order_Block_bajista_2.time1, time[0]) == 0)
| |||
{
| |||
newVela_Order_Block_bajista_2.mitigated = false;
| |||
newVela_Order_Block_bajista_2.name = code_obj + "bear_" + TimeToString(newVela_Order_Block_bajista_2.time1);
| |||
AddArray(bearish_ob, newVela_Order_Block_bajista_2); //we add the structure to the array
| |||
}
| |||
}
| |||
| |||
if(ArraySize(buy_volume) >= 5 && ArraySize(sell_volume) >= 5 && use_market_book == true)
| |||
{
| |||
const double ratio = 1.4;
| |||
bool case_book = sell_volume[3] > buy_volume[4] * ratio && sell_volume[3] > buy_volume[2] * ratio &&
| |||
sell_volume[3] > sell_volume[4] * ratio && sell_volume[3] > sell_volume[2] * ratio;
| |||
| |||
double body_tree = open[3] - close[3];
| |||
if(high[2] < (open[3] - (body_tree * 0.5)) && low[3] > close[2] && close[3] < open[3] && close[2] < open[2] && close[1] < open[1] && case_book)
| |||
{
| |||
int furthestBajista = FindFurthestBajista(time[3], 20, _Period, _Symbol);
| |||
if(furthestBajista > 0)
| |||
{
| |||
datetime time1 = time[furthestBajista];
| |||
double price1 = close[furthestBajista];
| |||
double price2 = low[furthestBajista];
| |||
newVela_Order_block_Book_bajista.price1 = price1;
| |||
newVela_Order_block_Book_bajista.time1 = time1;
| |||
newVela_Order_block_Book_bajista.case_book = true;
| |||
newVela_Order_block_Book_bajista.price2 = price2;
| |||
newVela_Order_block_Book_bajista.mitigated = false;
| |||
newVela_Order_block_Book_bajista.name = code_obj + "bear_" + TimeToString(newVela_Order_block_Book_bajista.time1);
| |||
AddArray(bearish_ob, newVela_Order_block_Book_bajista);
| |||
}
| |||
}
| |||
}
| |||
| |||
//--- Initial declaration of variables
| |||
static bool buscar_obb = true; //Flag indicating whether a bearish order block is being sought
| |||
static datetime time_b = 0; //Time in which the bearish order block was mitigated (to be able to schedule a maximum wait)
| |||
string curr_elimiandor_obb[]; //Array with the names of the order blocks that will be removed from the bearish_ob array
| |||
| |||
for(int i = 0; i < ArraySize(bearish_ob); i++)
| |||
{
| |||
datetime mitigadoTime = esOb_mitigado_array_bajista(bearish_ob[i], bearish_ob[i].time1);
| |||
| |||
if(bearish_ob[i].mitigated == false) //if it has not been mitigated
| |||
{
| |||
if(ObjectFind(ChartID(), bearish_ob[i].name) < 0) //If the object does not exist, we create it
| |||
{
| |||
const static string tools[2] = { "Order Block Bajista", "Order Block Bajista Book"};
| |||
RectangleCreate(ChartID(), bearish_ob[i].name, 0, bearish_ob[i].time1, bearish_ob[i].price1,
| |||
time[0], bearish_ob[i].price2, color_of_bearish_ob, Witdth_order_block, Fill_order_block, Back_order_block, STYLE_SOLID, false, tools[int(bearish_ob[i].case_book)]);
| |||
}
| |||
else //If it exists, we update it (we only move anchor point 1)
| |||
ObjectSetInteger(ChartID(), bearish_ob[i].name, OBJPROP_TIME, 1, time[0]);
| |||
}
| |||
else
| |||
{
| |||
//A bearish order block has been mitigated
| |||
if(enable_alerts)
| |||
Alert("The bearish order block is being mitigated: ", TimeToString(bearish_ob[i].time1)); //We print an alert
| |||
AddArrayNoVerification(pricetwo_eliminados_obb, bearish_ob[i].name); //To be able to remove the rectangle from the order block we save its name
| |||
AddArrayNoVerification(curr_elimiandor_obb, bearish_ob[i].name); //We add to the string array so that it is removed from the main array
| |||
| |||
if(buscar_obb == true) //If we search for obb, it means that we are searching for a signal, so we initialize the start time time_b with the current one, (this is to calculate the maximum wait)
| |||
{
| |||
time_b = iTime(_Symbol, _Period, 0);
| |||
buscar_obb = false;
| |||
}
| |||
| |||
}
| |||
}
| |||
| |||
for(int i = 0; i < ArraySize(curr_elimiandor_obb) ; i++)
| |||
DeleteArrayBiName(bearish_ob, curr_elimiandor_obb[i]); //We remove the indicated name from the array (name)
| |||
| |||
if(buscar_obb == false && time_b > 0)
| |||
{
| |||
double close_ = NormalizeDouble(close[1], _Digits); //We normalize the price
| |||
datetime max_time_espera = time_b + (PeriodSeconds() * 5); //Maximum wait 5 candles to confirm the break of the moving average
| |||
if(close_ < ma[1] && time[0] <= max_time_espera) //We verify that the previous close is lower than the value of the previous EMA and that the last opening time is less than the maximum wait
| |||
{
| |||
double bid = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits); //Obtenmos el bid
| |||
double tp1, tp2, sl1, sl2;
| |||
| |||
GetTP_SL(bid, POSITION_TYPE_SELL, tp1, tp2, sl1, sl2); //We get the tp, sl
| |||
DrawTP_SL(tp1, tp2, sl1, sl2); //We draw
| |||
| |||
//--- Let's assign to the buffers
| |||
tp1_buffer[0] = tp1;
| |||
tp2_buffer[0] = tp2;
| |||
sl1_buffer[0] = sl1;
| |||
sl2_buffer[0] = sl2;
| |||
| |||
//---
| |||
sell_buffer[0] = bid + atr[0] * 1.3;
| |||
| |||
//--- We reset the variables
| |||
time_b = 0;
| |||
buscar_obb = true;
| |||
}
| |||
if(time[0] > max_time_espera) //If the maximum wait is exceeded, we also restart and look for another mitigated bearish order block.
| |||
{
| |||
time_b = 0;
| |||
buscar_obb = true;
| |||
}
| |||
}
| |||
}
| |||
| |||
//--- return value of prev_calculated for next call
| |||
return(rates_total);
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
void OnDeinit(const int reason)
| |||
{
| |||
//---
| |||
Eliminar_Objetos();
| |||
ArrayFree(bearish_ob);
| |||
ArrayFree(bullish_ob);
| |||
| |||
if(atr_i != INVALID_HANDLE)
| |||
IndicatorRelease(atr_i);
| |||
if(hanlde_ma != INVALID_HANDLE)
| |||
IndicatorRelease(hanlde_ma);
| |||
| |||
ResetLastError();
| |||
//---
| |||
if(MarketBookRelease(_Symbol)) //Verificamos si el cierre fue exitoso
| |||
ob_logger.LogInfo("Market book closed successfully", ORDER_BLOCK_IND_NAME);
| |||
else
| |||
ob_logger.LogWarning(StringFormat("Order book not closed successfully, last error description = %s", ErrorDescription(GetLastError())), ORDER_BLOCK_IND_NAME);
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
void OnBookEvent(const string& symbol)
| |||
{
| |||
if(symbol != _Symbol || use_market_book == false)
| |||
return;
| |||
| |||
MqlBookInfo book_info[];
| |||
bool book_count = MarketBookGet(_Symbol, book_info);
| |||
| |||
if(book_count == true)
| |||
{
| |||
for(int i = 0; i < ArraySize(book_info); i++)
| |||
{
| |||
if(book_info[i].type == BOOK_TYPE_BUY || book_info[i].type == BOOK_TYPE_BUY_MARKET)
| |||
buy_volume[0] += book_info[i].volume;
| |||
else
| |||
if(book_info[i].type == BOOK_TYPE_SELL || book_info[i].type == BOOK_TYPE_SELL_MARKET)
| |||
sell_volume[0] += book_info[i].volume;
| |||
}
| |||
}
| |||
else
| |||
{
| |||
ob_logger.LogWarning("No data has been obtained from the Market Book.", ORDER_BLOCK_IND_NAME);
| |||
}
| |||
}
| |||
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| |
| |||
//+------------------------------------------------------------------+
| |||
void OnChartEvent(const int id,
| |||
const long &lparam,
| |||
const double &dparam,
| |||
const string &sparam)
| |||
{
| |||
if(id == CHARTEVENT_CHART_CHANGE && lparam == 3)
| |||
{
| |||
color_of_bullish_ob = ApplyTransparency(Color_Order_Block_Alcista, transparecy);
| |||
color_of_bearish_ob = ApplyTransparency(Color_Order_Block_Bajista, transparecy);
| |||
ModificarColor();
| |||
}
| |||
}
| |||
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Array |
| |||
//+------------------------------------------------------------------+
| |||
template <typename S>
| |||
bool AddArray(S &Array[], const S &Value)
| |||
{
| |||
for(int i = 0 ; i < ArraySize(Array) ; i++)
| |||
{
| |||
if(Array[i].name == Value.name)
| |||
return false;
| |||
}
| |||
ArrayResize(Array, Array.Size() + 1);
| |||
Array[Array.Size() - 1] = Value;
| |||
return true;
| |||
}
| |||
| |||
template <typename X>
| |||
void AddArrayNoVerification(X &array[], const X &value)
| |||
{
| |||
ArrayResize(array, array.Size() + 1);
| |||
array[array.Size() - 1] = value;
| |||
}
| |||
| |||
template<typename T>
| |||
bool DeleteArrayBiName(T &array[], const string targetName)
| |||
{
| |||
int size = ArraySize(array);
| |||
int index = -1;
| |||
| |||
| |||
for(int i = 0; i < size; i++)
| |||
{
| |||
if(array[i].name == targetName)
| |||
{
| |||
index = i;
| |||
}
| |||
if(index != -1 && i < size - 1)
| |||
{
| |||
array[i] = array[i + 1]; // Move the elements
| |||
}
| |||
}
| |||
| |||
if(index == -1)
| |||
return false;
| |||
| |||
if(size > 1)
| |||
ArrayResize(array, size - 1);
| |||
else
| |||
ArrayFree(array); // If the array had only one element, it is completely freed
| |||
| |||
return true;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| |
| |||
//+------------------------------------------------------------------+
| |||
datetime IsBullishObMitigated(double price, const double &lowArray[], const datetime &Time[], datetime start, datetime end)
| |||
{
| |||
int startIndex = iBarShift(_Symbol, PERIOD_CURRENT, start);
| |||
int endIndex = iBarShift(_Symbol, PERIOD_CURRENT, end);
| |||
| |||
NormalizeDouble(price, _Digits);
| |||
for(int i = startIndex - 2 ; i >= endIndex + 1 ; i--)
| |||
{
| |||
if(price > lowArray[i])
| |||
{
| |||
return Time[i];//if it finds that there was, it returns the time of the candle where the mitigation occurred
| |||
}
| |||
}
| |||
| |||
return 0;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
datetime mitigado_bajista(double price, const double &highArray[], const datetime &Time[], datetime start, datetime end)
| |||
{
| |||
int startIndex = iBarShift(_Symbol, PERIOD_CURRENT, start);
| |||
int endIndex = iBarShift(_Symbol, PERIOD_CURRENT, end);
| |||
NormalizeDouble(price, _Digits);
| |||
for(int i = startIndex - 2 ; i >= endIndex + 1 ; i--)
| |||
{
| |||
if(highArray[i] > price)
| |||
{
| |||
return Time[i]; ///if it finds that there was, it returns the time of the candle where the mitigation occurred
| |||
}
| |||
}
| |||
return 0;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
datetime IsBullishOrderBlockMitigated(OrderBlocks &newblock, datetime end)
| |||
{
| |||
int endIndex = iBarShift(_Symbol, PERIOD_CURRENT, end) - 2;
| |||
if(endIndex < 0)
| |||
return 0;
| |||
| |||
for(int i = 0 ; i < endIndex; i++)
| |||
{
| |||
double low = iLow(_Symbol, PERIOD_CURRENT, i);
| |||
if(newblock.price2 >= low)
| |||
{
| |||
newblock.mitigated = true;
| |||
newblock.time2 = iTime(_Symbol, _Period, i);
| |||
return newblock.time2;//returns the time of the candle found
| |||
}
| |||
}
| |||
return 0;// not mitigated so far
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
datetime esOb_mitigado_array_bajista(OrderBlocks &newblock, datetime end)
| |||
{
| |||
int endIndex = iBarShift(_Symbol, PERIOD_CURRENT, end) - 2;
| |||
if(endIndex < 0)
| |||
return 0;
| |||
| |||
for(int i = 0 ; i < endIndex ; i++)
| |||
{
| |||
double high = iHigh(_Symbol, PERIOD_CURRENT, i);
| |||
if(high >= newblock.price2)
| |||
{
| |||
newblock.mitigated = true;
| |||
newblock.time2 = iTime(_Symbol, _Period, i);
| |||
return newblock.time2;
| |||
}
| |||
}
| |||
return 0; // not mitigated so far
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
int FindFurthestBajista(datetime start, int numVelas, ENUM_TIMEFRAMES timeframe, string symbol)
| |||
{
| |||
int startVela = iBarShift(symbol, timeframe, start);
| |||
| |||
for(int i = startVela + 1, c = 0; i <= startVela + numVelas; i++, c++)
| |||
{
| |||
if(iClose(symbol, timeframe, i) > iOpen(symbol, timeframe, i))
| |||
return startVela + 1 + c;
| |||
}
| |||
| |||
return -1;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
int FindFurthestAlcista(datetime start, int numVelas, ENUM_TIMEFRAMES timeframe, string symbol)
| |||
{
| |||
int startVela = iBarShift(symbol, timeframe, start);
| |||
| |||
for(int i = startVela + 1, c = 0; i <= startVela + numVelas; i++, c++)
| |||
{
| |||
if(iClose(symbol, timeframe, i) < iOpen(symbol, timeframe, i))
| |||
return startVela + 1 + c;
| |||
}
| |||
| |||
return -1;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| TP-SL |
| |||
//+------------------------------------------------------------------+
| |||
void GetTP_SL(double price_open_position, ENUM_POSITION_TYPE type, double &tp1, double &tp2, double &sl1, double &sl2)
| |||
{
| |||
if(CopyBuffer(atr_i, 0, 0, 1, atr) < 1)
| |||
{
| |||
return;
| |||
}
| |||
| |||
if(tp_sl_style == ATR)
| |||
{
| |||
if(type == POSITION_TYPE_BUY)
| |||
{
| |||
sl1 = price_open_position - (atr[0] * Atr_Multiplier_1);
| |||
sl2 = price_open_position - (atr[0] * Atr_Multiplier_2);
| |||
tp1 = price_open_position + (atr[0] * Atr_Multiplier_1);
| |||
tp2 = price_open_position + (atr[0] * Atr_Multiplier_2);
| |||
}
| |||
if(type == POSITION_TYPE_SELL)
| |||
{
| |||
sl1 = price_open_position + (atr[0] * Atr_Multiplier_1);
| |||
sl2 = price_open_position + (atr[0] * Atr_Multiplier_2);
| |||
tp1 = price_open_position - (atr[0] * Atr_Multiplier_1);
| |||
tp2 = price_open_position - (atr[0] * Atr_Multiplier_2);
| |||
}
| |||
}
| |||
else
| |||
if(tp_sl_style == POINT)
| |||
{
| |||
if(type == POSITION_TYPE_BUY)
| |||
{
| |||
sl1 = price_open_position - (SL_POINT * _Point);
| |||
sl2 = price_open_position - (SL_POINT * _Point * 2);
| |||
tp1 = price_open_position + (TP_POINT * _Point);
| |||
tp2 = price_open_position + (TP_POINT * _Point * 2);
| |||
}
| |||
if(type == POSITION_TYPE_SELL)
| |||
{
| |||
sl1 = price_open_position + (SL_POINT * _Point);
| |||
sl2 = price_open_position + (SL_POINT * _Point * 2);
| |||
tp1 = price_open_position - (TP_POINT * _Point);
| |||
tp2 = price_open_position - (TP_POINT * _Point * 2);
| |||
}
| |||
}
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
void DrawTP_SL(double tp1, double tp2, double sl1, double sl2)
| |||
{
| |||
string curr_time = "ENTRY" + TimeToString(iTime(_Symbol, _Period, 0));
| |||
datetime extension_time = iTime(_Symbol, _Period, 0) + (PeriodSeconds(PERIOD_CURRENT) * 15);
| |||
datetime text_time = extension_time + (PeriodSeconds(PERIOD_CURRENT) * 2);
| |||
// Print("SL1: " , sl1 , " SL2: " , sl2 , " TP1: " , tp1 , " TP2: " , tp2);
| |||
TrendCreate(0, curr_time + " TP1", 0, iTime(_Symbol, _Period, 0), tp1, extension_time, tp1, clrGreen, STYLE_DOT, 1, true, false);
| |||
TextCreate(0, curr_time + " TP1 - Text", 0, text_time, tp1, "TP1", "Arial", 8, clrGreen, 0.0, ANCHOR_CENTER);
| |||
TrendCreate(0, curr_time + " TP2", 0, iTime(_Symbol, _Period, 0), tp2, extension_time, tp2, clrGreen, STYLE_DOT, 1, true, false);
| |||
TextCreate(0, curr_time + " TP2 - Text", 0, text_time, tp2, "TP2", "Arial", 8, clrGreen, 0.0, ANCHOR_CENTER);
| |||
TrendCreate(0, curr_time + " SL1", 0, iTime(_Symbol, _Period, 0), sl1, extension_time, sl1, clrRed, STYLE_DOT, 1, true, false);
| |||
TextCreate(0, curr_time + " SL1 - Text", 0, text_time, sl1, "SL1", "Arial", 8, clrRed, 0.0, ANCHOR_CENTER);
| |||
TrendCreate(0, curr_time + " SL2", 0, iTime(_Symbol, _Period, 0), sl2, extension_time, sl2, clrRed, STYLE_DOT, 1, true, false);
| |||
TextCreate(0, curr_time + " SL2 - Text", 0, text_time, sl2, "SL2", "Arial", 8, clrRed, 0.0, ANCHOR_CENTER);
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| OrderBlocks |
| |||
//+------------------------------------------------------------------+
| |||
void ModificarColor()
| |||
{
| |||
for(int i = 0; i < ArraySize(bullish_ob) ; i++)
| |||
ObjectSetInteger(0, bullish_ob[i].name, OBJPROP_COLOR, color_of_bullish_ob);
| |||
| |||
for(int i = 0; i < ArraySize(bearish_ob) ; i++)
| |||
ObjectSetInteger(0, bearish_ob[i].name, OBJPROP_COLOR, color_of_bearish_ob);
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
void Eliminar_Objetos() //Function to delete objects
| |||
{
| |||
ObjectsDeleteAll(0, "ENTRY", -1, -1);
| |||
for(int i = 0; i < ArraySize(pricetwo_eliminados_oba) ; i++)
| |||
ObjectDelete(0, pricetwo_eliminados_oba[i]);
| |||
for(int i = 0; i < ArraySize(pricetwo_eliminados_obb) ; i++)
| |||
ObjectDelete(0, pricetwo_eliminados_obb[i]);
| |||
for(int i = 0; i < ArraySize(bullish_ob) ; i++)
| |||
ObjectDelete(0, bullish_ob[i].name);
| |||
for(int i = 0; i < ArraySize(bearish_ob) ; i++)
| |||
ObjectDelete(0, bearish_ob[i].name);
| |||
| |||
ArrayFree(pricetwo_eliminados_oba);
| |||
ArrayFree(pricetwo_eliminados_obb);
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Funciones para la creacion de objetos |
| |||
//+------------------------------------------------------------------+
| |||
void RectangleCreate(long chart_ID, string name, const int sub_window, datetime time1, double price1, datetime time2,
| |||
double price2, color clr, int width, bool fill, bool back, ENUM_LINE_STYLE style, bool select, string tooltip)
| |||
{
| |||
ResetLastError(); //we reset the last error
| |||
//verification and creation of the rectangle
| |||
if(!ObjectCreate(chart_ID, name, OBJ_RECTANGLE, sub_window, time1, price1, time2, price2))
| |||
{
| |||
ob_logger.LogError(StringFormat("Failed to create rectangle: %s, last error description = %s", name, ErrorDescription(GetLastError())), ORDER_BLOCK_IND_NAME);
| |||
}
| |||
ObjectSetString(chart_ID, name, OBJPROP_TOOLTIP, tooltip);
| |||
ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr);
| |||
ObjectSetInteger(chart_ID, name, OBJPROP_STYLE, style);
| |||
ObjectSetInteger(chart_ID, name, OBJPROP_WIDTH, width);
| |||
ObjectSetInteger(chart_ID, name, OBJPROP_FILL, fill);
| |||
ObjectSetInteger(chart_ID, name, OBJPROP_BACK, back);
| |||
ObjectSetInteger(chart_ID, name, OBJPROP_SELECTABLE, select);
| |||
ObjectSetInteger(chart_ID, name, OBJPROP_SELECTED, select);
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
bool TrendCreate(long chart_ID,
| |||
string name,
| |||
int sub_window,
| |||
datetime time1,
| |||
double price1,
| |||
datetime time2,
| |||
double price2,
| |||
color clr,
| |||
ENUM_LINE_STYLE style,
| |||
int width,
| |||
bool back,
| |||
bool selection
| |||
)
| |||
{
| |||
ResetLastError();
| |||
//--- We create the trend line according to the established coordinates
| |||
if(!ObjectCreate(chart_ID, name, OBJ_TREND, sub_window, time1, price1, time2, price2))
| |||
{
| |||
ob_logger.LogError(StringFormat("Failed to create trend_line: %s, last error description = %s", name, ErrorDescription(GetLastError())), ORDER_BLOCK_IND_NAME);
| |||
return(false);
| |||
}
| |||
ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr);
| |||
ObjectSetInteger(chart_ID, name, OBJPROP_STYLE, style);
| |||
ObjectSetInteger(chart_ID, name, OBJPROP_WIDTH, width);
| |||
ObjectSetInteger(chart_ID, name, OBJPROP_BACK, back);
| |||
ObjectSetInteger(chart_ID, name, OBJPROP_SELECTABLE, selection);
| |||
ObjectSetInteger(chart_ID, name, OBJPROP_SELECTED, selection);
| |||
| |||
//---
| |||
return(true);
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
bool TextCreate(long chart_ID,
| |||
string name,
| |||
int sub_window,
| |||
datetime time,
| |||
double price,
| |||
string text,
| |||
string font,
| |||
int font_size,
| |||
color clr,
| |||
double angle,
| |||
ENUM_ANCHOR_POINT anchor,
| |||
bool back = false,
| |||
bool selection = false)
| |||
| |||
| |||
{
| |||
ResetLastError();
| |||
//--- we create the "Text" object
| |||
if(!ObjectCreate(chart_ID, name, OBJ_TEXT, sub_window, time, price))
| |||
{
| |||
ob_logger.LogError(StringFormat("Failed to create text: %s, last error description = %s", name, ErrorDescription(GetLastError())), ORDER_BLOCK_IND_NAME);
| |||
return(false);
| |||
}
| |||
ObjectSetString(chart_ID, name, OBJPROP_TEXT, text);
| |||
ObjectSetString(chart_ID, name, OBJPROP_FONT, font);
| |||
ObjectSetInteger(chart_ID, name, OBJPROP_FONTSIZE, font_size);
| |||
ObjectSetDouble(chart_ID, name, OBJPROP_ANGLE, angle);
| |||
ObjectSetInteger(chart_ID, name, OBJPROP_ANCHOR, anchor);
| |||
ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr);
| |||
ObjectSetInteger(chart_ID, name, OBJPROP_BACK, back);
| |||
ObjectSetInteger(chart_ID, name, OBJPROP_SELECTABLE, selection);
| |||
ObjectSetInteger(chart_ID, name, OBJPROP_SELECTED, selection);
| |||
return(true);
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Transparencia |
| |||
//+------------------------------------------------------------------+
| |||
color ApplyTransparency(color fg, double alpha)
| |||
{
| |||
// Clamp alpha between 0.0 and 1.0
| |||
alpha = MathMax(0.0, MathMin(1.0, alpha));
| |||
| |||
// Get background color of the current chart
| |||
long bg_long;
| |||
if(!ChartGetInteger(0, CHART_COLOR_BACKGROUND, 0, bg_long))
| |||
bg_long = clrWhite; // Fallback if it fails
| |||
| |||
color bg = (color)bg_long;
| |||
| |||
// Decompose foreground color
| |||
int r_fg = (fg >> 16) & 0xFF;
| |||
int g_fg = (fg >> 8) & 0xFF;
| |||
int b_fg = fg & 0xFF;
| |||
| |||
// Decompose background color
| |||
int r_bg = (bg >> 16) & 0xFF;
| |||
int g_bg = (bg >> 8) & 0xFF;
| |||
int b_bg = bg & 0xFF;
| |||
| |||
// Blend each channel
| |||
int r = (int)(r_fg * alpha + r_bg * (1.0 - alpha));
| |||
int g = (int)(g_fg * alpha + g_bg * (1.0 - alpha));
| |||
int b = (int)(b_fg * alpha + b_bg * (1.0 - alpha));
| |||
| |||
// Compose final color
| |||
return (color)((r << 16) | (g << 8) | b);
| |||
}
| |||
//+------------------------------------------------------------------+
|