MQLArticles/Utils/Fibonacci.mqh

500 lines
34 KiB
MQL5

2025-09-22 09:08:13 -05:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| Fibonacci.mqh |
//| Copyright 2025, Niquel Mendoza. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
2025-11-10 09:33:53 -05:00
#property copyright "Copyright 2025, Niquel Mendoza."
2025-09-22 09:08:13 -05:00
#property link "https://www.mql5.com"
2025-11-28 07:28:13 -05:00
2025-09-22 09:08:13 -05:00
#property strict
2025-11-17 10:27:47 -05:00
#ifndef MQLARTICLES_UTILS_FIBONACCI_MQH
2025-09-22 09:08:13 -05:00
#define MQLARTICLES_UTILS_FIBONACCI_MQH
2025-11-17 10:27:47 -05:00
#include "..\\Utils\\GraphicObjects.mqh"
2025-09-22 09:08:13 -05:00
#include "FA\\Sort.mqh"
2025-11-17 10:27:47 -05:00
2025-09-22 09:08:13 -05:00
//+------------------------------------------------------------------+
//| |
2025-11-28 07:28:13 -05:00
//+------------------------------------------------------------------+
2025-11-30 07:45:17 -05:00
2025-11-28 07:28:13 -05:00
struct pack(8) FibboLevel
2025-11-30 07:45:17 -05:00
2025-11-28 07:28:13 -05:00
{
2025-09-22 09:08:13 -05:00
double level_price;
double level_value;
2025-11-17 10:27:47 -05:00
2025-09-22 09:08:13 -05:00
color level_color;
FibboLevel()
: level_color(clrBlack), level_price(0.00), level_value(0.00)
{
2025-11-17 10:27:47 -05:00
}
FibboLevel(const FibboLevel& other)
2025-09-22 09:08:13 -05:00
{
2025-11-17 10:27:47 -05:00
this = other;
}
2025-09-22 09:08:13 -05:00
2025-11-17 10:27:47 -05:00
2025-09-22 09:08:13 -05:00
//---
2025-11-17 10:27:47 -05:00
static __forceinline bool MayorLevel(const FibboLevel& f1, const FibboLevel& f2)
2025-09-22 09:08:13 -05:00
{
return f1.level_value > f2.level_value;
}
};
enum ENUM_MODE_NEAREST_LEVEL_FIBBO
{
FIBBO_LEVEL_MAYOR_A_TARGE_PRICE = 0,
FIBBO_LEVEL_MENOR_A_TARGE_PRICE,
2025-09-22 09:08:13 -05:00
};
2025-09-22 09:08:13 -05:00
//+------------------------------------------------------------------+
2025-11-28 07:28:13 -05:00
2025-09-22 09:08:13 -05:00
//| |
//+------------------------------------------------------------------+
2025-11-17 10:27:47 -05:00
class CFibbo : public CLoggerBase
2025-09-22 09:08:13 -05:00
{
2025-11-17 10:27:47 -05:00
private:
//--- Caracteristicas principales
long m_chart_id;
int m_subwin;
bool m_create; //Indica si el fibbo ha sido creado
2025-09-22 09:08:13 -05:00
//--- Caracteristicas del fibbo
2025-11-17 10:27:47 -05:00
string m_obj_name;
double m_price_2;
double m_price_1;
datetime m_init_fibbo;
//---
CHashMap<double, int> m_hash_level_to_index;
//---
2025-11-17 10:27:47 -05:00
int m_total_fibbo;
2025-09-22 09:08:13 -05:00
FibboLevel m_fibbo_levels[];
//--- Add
2025-11-17 10:27:47 -05:00
bool AddLevel(const FibboLevel &new_level);
2025-09-22 09:08:13 -05:00
2025-11-17 10:27:47 -05:00
//---
2025-09-22 09:08:13 -05:00
2025-11-17 10:27:47 -05:00
void CalculatePriceLevelsFibbo();
2025-09-22 09:08:13 -05:00
public:
2025-11-17 10:27:47 -05:00
CFibbo();
2025-09-22 09:08:13 -05:00
2025-11-17 10:27:47 -05:00
~CFibbo(void);
//--- Creacion
2025-09-22 09:08:13 -05:00
bool Create(const long chart_ID,
const string name,
2025-11-17 10:27:47 -05:00
const int sub_window,
2025-11-30 07:45:17 -05:00
const color clr,
2025-11-17 10:27:47 -05:00
2025-09-22 09:08:13 -05:00
const ENUM_LINE_STYLE style,
2025-11-30 07:45:17 -05:00
2025-09-22 09:08:13 -05:00
const int width,
const string tooltip,
const bool back = false,
2025-11-17 10:27:47 -05:00
const bool selection = false,
const long z_order = 0);
2025-09-22 09:08:13 -05:00
//--- Seteo - Modifiacion de nivel-niveeles
2025-11-17 10:27:47 -05:00
bool SetLevels(string vals, string clrs, ENUM_LINE_STYLE styles, int widths, ushort separator_str);
2025-09-22 09:08:13 -05:00
__forceinline uint8_t ModifyLevel(double level, color new_color = clrNONE, ENUM_LINE_STYLE new_style = WRONG_VALUE, int new_widt = -1);
uint8_t ModifyLevel(int level_index, color new_color = clrNONE, ENUM_LINE_STYLE new_style = WRONG_VALUE, int new_widt = -1);
2025-11-17 10:27:47 -05:00
2025-09-22 09:08:13 -05:00
//--- Funciones para trabajar con el objeto grafico
2025-11-17 10:27:47 -05:00
void Move(datetime new_init, datetime new_end, double price1, double price2); // Momer el fibbo completamente
2025-09-22 09:08:13 -05:00
2025-11-17 10:27:47 -05:00
__forceinline void UpdateTime2(datetime new_end); //Solo actulizar el fibbo a un nuevo time2
bool Hide() const { return HIDE_OBJECT(m_obj_name, m_chart_id); }
bool Show() const { return SHOW_OBJECT(m_obj_name, m_chart_id); }
//--- Funciones para trabajar con niveles
// Obtiene el precio de un nivel por su el valor del nivel
2025-09-22 09:08:13 -05:00
__forceinline double GetLevelPrice(const double level_val);
2025-11-17 10:27:47 -05:00
2025-09-22 09:08:13 -05:00
// Obtiene el precio de un nivel por su indice real
2025-11-17 10:27:47 -05:00
__forceinline double GetLevelPrice(const int level_index) const { return m_fibbo_levels[level_index].level_price; }
2025-09-22 09:08:13 -05:00
2025-11-17 10:27:47 -05:00
// Obtiene el indice en el array de un nivel
__forceinline int GetLevelIndex(const double level_val);
// Obtiene los niveles del fibbo
2025-09-22 09:08:13 -05:00
void GetArrayLevel(double &levels[], bool contains_lebel_0_100 = false) const;
2025-11-17 10:27:47 -05:00
double GetNearestLevel(double target_price, ENUM_MODE_NEAREST_LEVEL_FIBBO mode) const;
2025-09-22 09:08:13 -05:00
2025-11-17 10:27:47 -05:00
//--- Getters y Setters generales
2025-09-22 09:08:13 -05:00
// Generales
inline int TotalFibboLevels() const { return m_total_fibbo; }
inline double Price1() const { return m_price_1; }
2025-09-22 09:08:13 -05:00
inline double Price2() const { return m_price_2; }
inline datetime InitTime() const { return m_init_fibbo; }
2025-09-22 09:08:13 -05:00
inline long ChartId() const { return m_chart_id; }
2025-11-17 10:27:47 -05:00
inline int Subwin() const { return m_subwin; }
2025-09-22 09:08:13 -05:00
__forceinline int FibboLevelLastIndex() const { return m_total_fibbo - 1; }
2025-11-17 10:27:47 -05:00
// Obtencion de un nivel
// Por indice
__forceinline FibboLevel GetLevelByIndex(const int idx) const { return m_fibbo_levels[idx]; }
2025-09-22 09:08:13 -05:00
2025-11-17 10:27:47 -05:00
2025-09-22 09:08:13 -05:00
// Por valor
__forceinline FibboLevel GetLevelByValue(const double val) { return m_fibbo_levels[GetLevelIndex(val)]; }
2025-11-17 10:27:47 -05:00
2025-09-22 09:08:13 -05:00
//--- Info
void Summary();
2025-11-17 10:27:47 -05:00
};
2025-09-22 09:08:13 -05:00
2025-11-17 10:27:47 -05:00
2025-09-22 09:08:13 -05:00
2025-11-17 10:27:47 -05:00
2025-09-22 09:08:13 -05:00
//+------------------------------------------------------------------+
//| |
2025-11-17 10:27:47 -05:00
//+------------------------------------------------------------------+
CFibbo::~CFibbo()
2025-09-22 09:08:13 -05:00
{
2025-11-17 10:27:47 -05:00
ObjectDelete(m_chart_id, m_obj_name);
2025-09-22 09:08:13 -05:00
2025-11-17 10:27:47 -05:00
}
2025-09-22 09:08:13 -05:00
//+------------------------------------------------------------------+
2025-11-17 10:27:47 -05:00
CFibbo::CFibbo()
2025-09-22 09:08:13 -05:00
: m_init_fibbo(wrong_datetime), m_price_2(0.00), m_price_1(0.00), m_subwin(0), m_chart_id(0), m_total_fibbo(0)
2025-11-17 10:27:47 -05:00
2025-09-22 09:08:13 -05:00
{
2025-11-17 10:27:47 -05:00
ArrayResize(m_fibbo_levels, 0);
2025-09-22 09:08:13 -05:00
}
2025-11-17 10:27:47 -05:00
2025-09-22 09:08:13 -05:00
//+------------------------------------------------------------------+
2025-11-17 10:27:47 -05:00
//| |
2025-09-22 09:08:13 -05:00
//+------------------------------------------------------------------+
2025-11-17 10:27:47 -05:00
2025-09-22 09:08:13 -05:00
void CFibbo::Summary(void)
{
2025-11-17 10:27:47 -05:00
2025-09-22 09:08:13 -05:00
PrintFormat("------| Fibbo %s |------", m_obj_name);
2025-11-17 10:27:47 -05:00
2025-09-22 09:08:13 -05:00
Print("Levels: ");
ArrayPrint(m_fibbo_levels, 3, " | ");
2025-11-17 10:27:47 -05:00
2025-09-22 09:08:13 -05:00
}
2025-09-22 09:08:13 -05:00
//+------------------------------------------------------------------+
2025-11-17 10:27:47 -05:00
bool CFibbo::AddLevel(const FibboLevel &new_level)
{
//--- Verificar si esta dentro
2025-11-17 10:27:47 -05:00
//Considerar esto, de pormedio un fibbo level como maximo tiene 3 decimales
2025-09-22 09:08:13 -05:00
#define CFIBBO_MIN_VALUE 0.00040
for(int i = 0; i < m_total_fibbo; i++)
2025-11-17 10:27:47 -05:00
2025-09-22 09:08:13 -05:00
{
2025-11-17 10:27:47 -05:00
if(fabs(m_fibbo_levels[i].level_value - new_level.level_value) <= CFIBBO_MIN_VALUE)
2025-09-22 09:08:13 -05:00
2025-11-17 10:27:47 -05:00
{
LogWarning(StringFormat("No se agregara el fibbo level %f dado que ya existe", new_level.level_value), FUNCION_ACTUAL);
return false;
2025-09-22 09:08:13 -05:00
}
2025-11-17 10:27:47 -05:00
}
//--- A<EFBFBD>adir
ArrayResize(m_fibbo_levels, m_total_fibbo + 1);
m_fibbo_levels[m_total_fibbo] = new_level;
m_total_fibbo++;
return true;
}
2025-09-22 09:08:13 -05:00
//+------------------------------------------------------------------+
2025-11-28 07:28:13 -05:00
2025-09-22 09:08:13 -05:00
double CFibbo::GetNearestLevel(double target_price, ENUM_MODE_NEAREST_LEVEL_FIBBO mode) const
2025-11-17 10:27:47 -05:00
{
2025-09-22 09:08:13 -05:00
2025-11-17 10:27:47 -05:00
//---
2025-09-22 09:08:13 -05:00
2025-11-17 10:27:47 -05:00
if(m_total_fibbo == 0)
2025-09-22 09:08:13 -05:00
return 0.00;
2025-11-17 10:27:47 -05:00
2025-09-22 09:08:13 -05:00
2025-11-17 10:27:47 -05:00
2025-09-22 09:08:13 -05:00
//---
2025-11-17 10:27:47 -05:00
2025-09-22 09:08:13 -05:00
const bool precio_ascendente = (m_fibbo_levels[0].level_price < m_fibbo_levels[m_total_fibbo - 1].level_price);
2025-11-17 10:27:47 -05:00
//---
2025-09-22 09:08:13 -05:00
if(mode == FIBBO_LEVEL_MAYOR_A_TARGE_PRICE)
{
if(precio_ascendente)
{
// Buscar de menor a mayor
for(int i = 0; i < m_total_fibbo; i++)
if(m_fibbo_levels[i].level_price > target_price)
return m_fibbo_levels[i].level_price;
}
2025-09-22 09:08:13 -05:00
else
{
// Buscar de mayor a menor (invertido)
2025-09-22 09:08:13 -05:00
for(int i = m_total_fibbo - 1; i >= 0; i--)
if(m_fibbo_levels[i].level_price > target_price)
return m_fibbo_levels[i].level_price;
}
2025-09-22 09:08:13 -05:00
}
else
2025-11-30 07:45:17 -05:00
{
2025-11-17 10:27:47 -05:00
2025-09-22 09:08:13 -05:00
if(precio_ascendente)
{
// Buscar el <EFBFBD>ltimo menor
for(int i = m_total_fibbo - 1; i >= 0; i--)
2026-01-02 10:22:09 -05:00
if(m_fibbo_levels[i].level_price < target_price)
return m_fibbo_levels[i].level_price;
2025-09-22 09:08:13 -05:00
}
else
{
// Buscar el primero menor (en orden descendente)
2025-11-30 07:45:17 -05:00
for(int i = 0; i < m_total_fibbo; i++)
2025-09-22 09:08:13 -05:00
2025-11-30 07:45:17 -05:00
if(m_fibbo_levels[i].level_price < target_price)
return m_fibbo_levels[i].level_price;
}
2025-09-22 09:08:13 -05:00
}
2025-11-17 10:27:47 -05:00
2025-09-22 09:08:13 -05:00
//---
2025-11-30 07:45:17 -05:00
2025-11-17 10:27:47 -05:00
LogWarning(StringFormat("No se ha encontrado nivel cercano al target price = %.*f", 5, target_price), FUNCION_ACTUAL);
2025-09-22 09:08:13 -05:00
2025-11-30 07:45:17 -05:00
return 0.00;
2025-11-17 10:27:47 -05:00
2025-09-22 09:08:13 -05:00
}
2025-11-17 10:27:47 -05:00
2025-09-22 09:08:13 -05:00
2025-11-17 10:27:47 -05:00
2025-09-22 09:08:13 -05:00
2025-11-17 10:27:47 -05:00
//+------------------------------------------------------------------+
2025-09-22 09:08:13 -05:00
2025-11-17 10:27:47 -05:00
bool CFibbo::Create(const long chart_ID,
2025-09-22 09:08:13 -05:00
2025-11-17 10:27:47 -05:00
const string name,
2025-09-22 09:08:13 -05:00
const int sub_window,
const color clr,
const ENUM_LINE_STYLE style,
2025-11-10 09:33:53 -05:00
2025-09-22 09:08:13 -05:00
const int width,