forked from rosh/MQL5Book
202 lines
6.7 KiB
MQL5
202 lines
6.7 KiB
MQL5
//+------------------------------------------------------------------+
| |
//| LibHoughChannel.mq5 |
| |
//| Copyright (c) 2015-2022, Marketeer |
| |
//| https://www.mql5.com/en/users/marketeer |
| |
//+------------------------------------------------------------------+
| |
#property copyright "Copyright (c) 2015-2022, Marketeer"
| |
#property link "https://www.mql5.com/en/users/marketeer"
| |
#property version "1.0"
| |
#property description "Create 2+ trend lines on highs and lows using Hough transform."
| |
| |
#property indicator_chart_window
| |
#property indicator_buffers 0
| |
#property indicator_plots 0
| |
| |
//#define LIB_HOUGH_IMPL_DEBUG
| |
#include "..\..\Include\LibHoughTransform.mqh"
| |
#include "..\..\Include\AutoPtr.mqh"
| |
| |
//+------------------------------------------------------------------+
| |
//| I N P U T S |
| |
//+------------------------------------------------------------------+
| |
input int BarOffset = 0;
| |
input int BarCount = 21;
| |
input int MaxLines = 3;
| |
| |
//+------------------------------------------------------------------+
| |
//| Custom implementation of HoughImage based on quotes |
| |
//+------------------------------------------------------------------+
| |
class HoughQuotes: public HoughImage<int>
| |
{
| |
public:
| |
enum PRICE_LINE
| |
{
| |
HighLow = 0, // Bar Range |High..Low|
| |
OpenClose = 1, // Bar Body |Open..Close|
| |
LowLow = 2, // Bar Lows
| |
HighHigh = 3, // Bar Highs
| |
};
| |
| |
protected:
| |
int size;
| |
int offset;
| |
int step;
| |
double base;
| |
PRICE_LINE type;
| |
| |
public:
| |
HoughQuotes(int startbar, int barcount, PRICE_LINE price)
| |
{
| |
offset = startbar;
| |
size = barcount;
| |
type = price;
| |
int hh = iHighest(NULL, 0, MODE_HIGH, size, startbar);
| |
int ll = iLowest(NULL, 0, MODE_LOW, size, startbar);
| |
int pp = (int)((iHigh(NULL, 0, hh) - iLow(NULL, 0, ll)) / _Point);
| |
step = pp / size;
| |
base = iLow(NULL, 0, ll);
| |
}
| |
| |
virtual int getWidth() const override
| |
{
| |
return size;
| |
}
| |
| |
virtual int getHeight() const override
| |
{
| |
return size;
| |
}
| |
| |
virtual int get(int x, int y) const override
| |
{
| |
if(offset + x >= iBars(NULL, 0)) return 0;
| |
| |
const double price = convert(y);
| |
if(type == HighLow)
| |
{
| |
if(price >= iLow(NULL, 0, offset + x) && price <= iHigh(NULL, 0, offset + x))
| |
{
| |
return 1;
| |
}
| |
}
| |
else if(type == OpenClose)
| |
{
| |
if(price >= fmin(iOpen(NULL, 0, offset + x), iClose(NULL, 0, offset + x))
| |
&& price <= fmax(iOpen(NULL, 0, offset + x), iClose(NULL, 0, offset + x)))
| |
{
| |
return 1;
| |
}
| |
}
| |
else if(type == LowLow)
| |
{
| |
if(iLow(NULL, 0, offset + x) >= price - step * _Point / 2
| |
&& iLow(NULL, 0, offset + x) <= price + step * _Point / 2)
| |
{
| |
return 1;
| |
}
| |
}
| |
else if(type == HighHigh)
| |
{
| |
if(iHigh(NULL, 0, offset + x) >= price - step * _Point / 2
| |
&& iHigh(NULL, 0, offset + x) <= price + step * _Point / 2)
| |
{
| |
return 1;
| |
}
| |
}
| |
return 0;
| |
}
| |
| |
// index by Y (quantized) -> continuous value (such as price)
| |
double convert(const double y) const
| |
{
| |
return base + y * step * _Point;
| |
}
| |
};
| |
| |
//+------------------------------------------------------------------+
| |
//| G L O B A L S |
| |
//+------------------------------------------------------------------+
| |
const string Prefix = "HoughChannel-";
| |
HoughTransform *ht;
| |
| |
//+------------------------------------------------------------------+
| |
//| Custom indicator initialization function |
| |
//+------------------------------------------------------------------+
| |
int OnInit()
| |
{
| |
ht = createHoughTransform(BarCount);
| |
HoughInfo info = getHoughInfo();
| |
Print(info.dimension, " per ", info.about);
| |
return CheckPointer(ht) != POINTER_INVALID ? INIT_SUCCEEDED : INIT_FAILED;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| Custom indicator iteration function |
| |
//+------------------------------------------------------------------+
| |
int OnCalculate(const int rates_total,
| |
const int prev_calculated,
| |
const int begin,
| |
const double &price[])
| |
{
| |
static datetime now = 0;
| |
if(now != iTime(NULL, 0, 0))
| |
{
| |
HoughQuotes highs(BarOffset, BarCount, HoughQuotes::HighHigh);
| |
HoughQuotes lows(BarOffset, BarCount, HoughQuotes::LowLow);
| |
static double result[];
| |
int n;
| |
n = ht.transform(highs, result, fmin(MaxLines, 5));
| |
if(n)
| |
{
| |
for(int i = 0; i < n; ++i)
| |
{
| |
DrawLine(highs, Prefix + "Highs-" + (string)i, result[i * 2 + 0], result[i * 2 + 1], clrBlue, 5 - i);
| |
}
| |
}
| |
else
| |
{
| |
Print("No solution for Highs");
| |
}
| |
n = ht.transform(lows, result, fmin(MaxLines, 5));
| |
if(n)
| |
{
| |
for(int i = 0; i < n; ++i)
| |
{
| |
DrawLine(lows, Prefix + "Lows-" + (string)i, result[i * 2 + 0], result[i * 2 + 1], clrRed, 5 - i);
| |
}
| |
}
| |
else
| |
{
| |
Print("No solution for Lows");
| |
}
| |
now = iTime(NULL, 0, 0);
| |
}
| |
return rates_total;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| Single line visual presenter |
| |
//+------------------------------------------------------------------+
| |
void DrawLine(HoughQuotes "es, const string name, const double a, const double b,
| |
const color clr, const int width)
| |
{
| |
ObjectCreate(0, name, OBJ_TREND, 0, 0, 0);
| |
ObjectSetInteger(0, name, OBJPROP_TIME, 0, iTime(NULL, 0, BarOffset + BarCount - 1));
| |
ObjectSetDouble(0, name, OBJPROP_PRICE, 0, quotes.convert(a * (BarCount - 1) + b));
| |
| |
ObjectSetInteger(0, name, OBJPROP_TIME, 1, iTime(NULL, 0, BarOffset));
| |
ObjectSetDouble(0, name, OBJPROP_PRICE, 1, quotes.convert(a * 0 + b));
| |
| |
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
| |
ObjectSetInteger(0, name, OBJPROP_WIDTH, width);
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| Finalization handler |
| |
//+------------------------------------------------------------------+
| |
void OnDeinit(const int)
| |
{
| |
AutoPtr<HoughTransform> destructor(ht);
| |
ObjectsDeleteAll(0, Prefix);
| |
}
| |
//+------------------------------------------------------------------+
|