last works on trend detector and try to test it inside x-test.ea.mq5 ...

This commit is contained in:
2024-07-10 16:01:33 +03:30
parent 6ba4fc1a70
commit 9ab980be84
3 changed files with 684 additions and 82 deletions
+30 -7
View File
@@ -63,6 +63,9 @@ XPivot lastResistancePivot;
XZone lastSupportZone; XZone lastSupportZone;
XZone lastResistanceZone; XZone lastResistanceZone;
//
XTrendDetector trendDetector;
// //
// Event Handlers ... // Event Handlers ...
@@ -157,6 +160,10 @@ void OnTick()
// //
// Check Time Tracker ... // Check Time Tracker ...
// HandleCheckTimeTracker(); // HandleCheckTimeTracker();
//
// Check Trend State ...
HandleCheckTrend();
} }
// //
@@ -524,38 +531,54 @@ void HandleCheckZones()
} }
// //
void HandleCheckTimeTracker() { void HandleCheckTimeTracker()
{
// //
// Month ... // Month ...
if (eaTimeTracker.IsNewMonth()) { if (eaTimeTracker.IsNewMonth())
{
eaAlert.Alert("New Month ..."); eaAlert.Alert("New Month ...");
} }
// //
// Week ... // Week ...
if (eaTimeTracker.IsNewWeek()) { if (eaTimeTracker.IsNewWeek())
{
eaAlert.Alert("New Week ..."); eaAlert.Alert("New Week ...");
} }
// //
// Day ... // Day ...
if (eaTimeTracker.IsNewDay()) { if (eaTimeTracker.IsNewDay())
{
eaAlert.Alert("New Day ..."); eaAlert.Alert("New Day ...");
} }
// //
// Hour ... // Hour ...
if (eaTimeTracker.IsNewHour()) { if (eaTimeTracker.IsNewHour())
{
eaAlert.Alert("New Hour ..."); eaAlert.Alert("New Hour ...");
} }
// //
// Minute ... // Minute ...
if (eaTimeTracker.IsNewMinute()) { if (eaTimeTracker.IsNewMinute())
{
eaAlert.Alert("New Minute ..."); eaAlert.Alert("New Minute ...");
} }
} }
//
void HandleCheckTrend()
{
//
bool hasTren = trendDetector.FindTrend(
_Symbol,
_Period //
);
}
// //
void OldTests() void OldTests()
{ {
@@ -693,5 +716,5 @@ void OldTests()
// eaBarTracker.Waits(); // eaBarTracker.Waits();
// } // }
} }
// //
+395
View File
@@ -0,0 +1,395 @@
/////////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 OrderBlock Detector Indicator
// -----------------------------------------------------
// Name: XOBD
// Description: detect Order Blocks based on Swings ...
//
//
// Maintainer:
// ------------
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
//
//////////////////////////////////////////////////////
//
// Global Properties ...
#property copyright "Copyright 2023, SaherElm IT Center"
#property link "https://saherelm.ir"
#property version "1.00"
#property description "SaherElm XOBD Indicator"
#property strict
//
// START Constants ...
//
#define ShortName "XOBD"
//
// END Constants ...
//
//
// START Inputs ...
//
//
input int length = 5; // Swing Length
//
input uchar swingHighArrowCode = 108; // Swing High Arrow Code
input color swingHighArrowColor = clrMagenta; // Swing High Arrow Color
//
input uchar swingLowArrowCode = 108; // Swing Low Arrow Code
input color swingLowArrowColor = clrAqua; // Swing Low Arrow Color
//
// END Inputs ...
//
//
// Include Common and Models Library ...
#include "../Libraries/x-saherelm.common.lib.mq5"
//
// Include Draw Library ...
#include "../Libraries/x-saherelm.draw.lib.mq5"
//
// START Buffers ...
//
#property indicator_chart_window
//
#property indicator_buffers 1
#property indicator_plots 0
//
#define swingBufferIndex 0
double swingBuffer[];
//
// END Buffers ...
//
//
// START Global Definitions: Variables, Properties and etc ...
//
//
// END Global Definitions: Variables, Properties and etc ...
//
//
// START Event Handlers ...
//
//
// Initialization ...
int OnInit()
{
//
// Validate Inputs ...
if (!ValidateInputs())
{
return INIT_PARAMETERS_INCORRECT;
}
//
drawPrefix = ShortName;
//
// Define Index Buffers ...
DefineBuffers();
//
// Set Indicator ShortName ...
SetIndicatorName();
//
// Init Succeed ...
return INIT_SUCCEEDED;
}
//
// DeInitialization ...
void OnDeinit(const int reason)
{
//
// REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function
// REASON_REMOVE 1 Program removed from a chart
// REASON_RECOMPILE 2 Program recompiled
// REASON_CHARTCHANGE 3 A symbol or a chart period is changed
// REASON_CHARTCLOSE 4 Chart closed
// REASON_PARAMETERS 5 Inputs changed by a user
// REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings
// REASON_TEMPLATE 7 Another chart template applied
// REASON_INITFAILED 8 The OnInit() handler returned a non-zero value
// REASON_CLOSE 9 Terminal closed
}
//
// Calculations ...
//
// Calculating what we want ...
int OnCalculate(
//
// total Candles on chart ...
const int rates_total,
//
// total calculated Candles on charts ...
const int prev_calculated,
//
// history of Candles Open Time ...
const datetime &time[],
//
// history of Candles Open Price ...
const double &open[],
//
// history of Candles High Price ...
const double &high[],
//
// history of Candles Low Price ...
const double &low[],
//
// history of Candles Close Price ...
const double &close[],
//
// history of Tick Volumes on Candle ...
const long &tick_volume[],
//
// history of Trade Volumes ...
const long &volume[],
//
// history of Candles Spread Price ...
const int &spread[])
{
//
// Prepare Buffers ...
ArraySetAsSeries(time, true);
ArraySetAsSeries(open, true);
ArraySetAsSeries(high, true);
ArraySetAsSeries(low, true);
ArraySetAsSeries(close, true);
ArraySetAsSeries(tick_volume, true);
ArraySetAsSeries(volume, true);
ArraySetAsSeries(spread, true);
//
// this counts Available Bars ...
int limit;
//
// because in some cases we may have more than one input for
// calculation and we must prevent any calculation
// untill we pass the biggest input length, here we get max Input length
// and then wait until pass it ...
int maxLength = MathMax(0, length * 3);
//
limit = prev_calculated < maxLength ? rates_total - (maxLength + 1) : rates_total - prev_calculated;
//
// Main Loop ...
for (int i = limit; i >= 0 && !IsStopped(); i--)
{
//
CalculateBuffers(i);
}
//
return rates_total;
}
//
// END Event Handlers ...
//
//
// START Functions ...
//
//
// Validate Input Args for Initialization ...
bool ValidateInputs()
{
//
bool result = false;
//
// Validate Args ...
if (length >= 2)
{
result = true;
}
//
return result;
}
//
// Define Indexes and Styles ...
void DefineBuffers()
{
//
ArraySetAsSeries(swingBuffer, true);
SetIndexBuffer(swingBufferIndex, swingBuffer, INDICATOR_CALCULATIONS);
}
//
// Set Indicator Short Name and also we can define Buffers Labels ...
void SetIndicatorName()
{
//
string indicatorShortName = "";
StringConcatenate(indicatorShortName, ShortName, " ", "( ", length, " )");
//
IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName);
}
//
// Calculate Buffers ...
void CalculateBuffers(int bar_index)
{
//
// GetCandleSwing(bar_index);
ENUM_X_SWING_TYPE type = X_NO_SWING;
//
// Try To Detect Order Blocks ...
bool isSwingLow = false;
bool isSwingHigh = false;
//
// Reading Candles Data ...
int start = bar_index;
int count = (length * 2) + 2;
int end = start + count;
XOHCL bars[];
int readedBars = GetBars(
bars,
_Symbol,
_Period,
start,
count
//
);
if (readedBars < count) {
return;
}
//
// Swing Low ...
isSwingLow =
//
bars[1].close > bars[2].close &&
bars[2].close > bars[3].close &&
//
bars[3].close < bars[4].close &&
//
bars[5].close > bars[4].close &&
bars[6].close > bars[5].close
//
;
//
if (isSwingLow)
{
type = X_SWING_LOW;
}
//
if (!isSwingLow)
{
//
// Swing High ...
isSwingHigh =
//
bars[1].close < bars[2].close &&
bars[2].close < bars[3].close &&
//
bars[3].close > bars[4].close &&
//
bars[5].close < bars[4].close &&
bars[6].close < bars[5].close
//
;
//
if (isSwingHigh)
{
type = X_SWING_HIGH;
}
}
//
switch (type)
{
//
// Swing High ...
case X_SWING_HIGH:
//
swingBuffer[bar_index] = type;
DrawSwingArrow(1, bar_index);
break;
//
// Swinmg Low ...
case X_SWING_LOW:
//
swingBuffer[bar_index] = type;
DrawSwingArrow(0, bar_index);
break;
//
// No Swing ...
default:
case X_NO_SWING:
//
swingBuffer[bar_index] = 0;
break;
}
}
//
// Draw a Swing Arrow Shape ...
void DrawSwingArrow(
int type, // Swing Type: 0 - Low / 1 - High ...
int bar_index //
)
{
//
bool isSwingHigh = type == 1;
//
if ((isSwingHigh && swingHighArrowCode == 0) ||
(!isSwingHigh && swingLowArrowCode == 0))
{
return;
}
XOHCL candle;
candle.Init(
_Symbol,
_Period,
bar_index + 3);
double arrowDistanceInPoint = 0;
//
// Define Required Object Properties fro Draw an Arrow ...
datetime time = iTime(_Symbol, _Period, bar_index + 3);
double purePrice = isSwingHigh ? candle.high : candle.low;
color clr = isSwingHigh ? swingHighArrowColor : swingLowArrowColor;
ENUM_ARROW_ANCHOR anchor = isSwingHigh ? ANCHOR_BOTTOM : ANCHOR_TOP;
uchar arrowCode = uchar(isSwingHigh ? swingHighArrowCode : swingLowArrowCode);
double price = isSwingHigh ? purePrice + arrowDistanceInPoint : purePrice - arrowDistanceInPoint;
string name = "Swing " + (isSwingHigh ? "High" : "Low") + "_" + (string)time + "_" + (string)purePrice;
//
// Draw desired Arrow ...
DrawArrow(
0,
name,
0,
time,
price,
arrowCode,
anchor,
clr);
}
//
// END Functions ...
//
+259 -75
View File
@@ -1426,7 +1426,8 @@ struct XZone
// //
// Check Zone Rejected ... // Check Zone Rejected ...
bool IsSupportRejected() { bool IsSupportRejected()
{
// //
bool result = false; bool result = false;
@@ -1434,17 +1435,17 @@ struct XZone
// Check is Full Support or Not ... // Check is Full Support or Not ...
ENUM_XZONE_STATE state = GetState(); ENUM_XZONE_STATE state = GetState();
result = state == XZONE_STATE_FULL_SUPPORT; result = state == XZONE_STATE_FULL_SUPPORT;
if (!result) { if (!result)
{
return result; return result;
} }
// //
// First Check Price Rejection Above Upper Line ... // First Check Price Rejection Above Upper Line ...
// //
return result; return result;
} }
// //
// Check Zone Breaked ... // Check Zone Breaked ...
@@ -1704,89 +1705,272 @@ struct XZone
// } // }
// }; // };
// // //
// // Detect Trends ... // Detect Trends ...
// struct XTrendDetector struct XTrendDetector
// { {
// // //
// string symbol; string symbol;
// ENUM_TIMEFRAMES period; ENUM_TIMEFRAMES period;
// // //
// double higherHighs[]; double higherHighs[];
// datetime higherHighTimes[]; datetime higherHighTimes[];
// // //
// double higherLows[]; double higherLows[];
// datetime higherLowTimes[]; datetime higherLowTimes[];
// // //
// double lowerHighs[]; double lowerHighs[];
// datetime lowerHighTimes[]; datetime lowerHighTimes[];
// // //
// double lowerLows[]; double lowerLows[];
// datetime lowerLowTimes[]; datetime lowerLowTimes[];
// // //
// int _numberOfPivots; int _numberOfPivots;
// int _pivotShoulders; int _pivotShoulders;
// // //
// // Constructor ... // Constructor ...
// XTrendDetector() XTrendDetector()
// { {
// Clean(); Clean();
// } }
// // //
// // Tools ... bool FindTrend(
string _symbol,
ENUM_TIMEFRAMES _period,
int barIndex = 0,
int _requiredPivots = 5,
int _requiredShoulders = 5 //
)
{
//
bool result = false;
// // //
// // Cleanup ... if (barIndex < 0)
// void Clean() {
// { barIndex = 0;
// // }
// symbol = NULL;
// period = NULL;
// // //
// _numberOfPivots = 0; if (_requiredPivots < 5)
// _pivotShoulders = 0; {
_requiredPivots = 5;
}
// // //
// Clean(higherHighs); if (_requiredShoulders < 5)
// Clean(higherHighTimes); {
_requiredShoulders = 5;
}
// // //
// Clean(higherLows); result =
// Clean(higherLowTimes); //
IsValid(_symbol) &&
IsValid(_period)
//
;
if (!result)
{
return result;
}
// // //
// Clean(lowerHighs); // Find Swing Lows and Swing Highs ...
// Clean(lowerHighTimes);
// // //
// Clean(lowerLows); int hhIndexes[];
// Clean(lowerLowTimes); datetime hhTimes[];
// } double hhs[];
// // //
// // Validate ... int llIndexes[];
// bool IsValid() datetime llTimes[];
// { double lls[];
// //
// bool result = false;
// // //
// result = bool isEnough = false;
// // int lastHHIndex = barIndex;
// IsValid(symbol) && int lastLLIndex = barIndex;
// IsValid(period) while (!isEnough)
// // {
// ; //
int hhSize = ArraySize(hhs);
if (hhSize < _requiredPivots)
{
//
lastHHIndex = FindSwing(
_symbol,
_period,
X_SWING_HIGH,
_requiredShoulders,
lastHHIndex + 1 //
);
if (lastHHIndex >= 0)
{
//
XOHCL hBar;
bool isInited = hBar.Init(
_symbol,
_period,
lastHHIndex //
);
if (isInited)
{
//
Add(
hBar.high,
hhs //
);
// // //
// return result; Add(
// } hBar.time,
// }; hhTimes //
);
//
Add(
lastHHIndex,
hhIndexes //
);
}
}
}
//
int llSize = ArraySize(lls);
if (llSize < _requiredPivots)
{
//
lastLLIndex = FindSwing(
_symbol,
_period,
X_SWING_LOW,
_requiredShoulders,
lastLLIndex + 1 //
);
if (lastLLIndex >= 0)
{
//
XOHCL lBar;
bool isInited = lBar.Init(
_symbol,
_period,
lastLLIndex //
);
if (isInited)
{
//
Add(
lBar.low,
lls //
);
//
Add(
lBar.time,
llTimes //
);
//
Add(
lastHHIndex,
llIndexes //
);
}
}
}
//
hhSize = ArraySize(hhs);
llSize = ArraySize(lls);
isEnough =
//
hhSize == _requiredPivots &&
llSize == _requiredPivots
//
;
}
// //
// ArrayReverse(hhs);
// ArrayReverse(hhTimes);
// ArrayReverse(hhIndexes);
// //
// ArrayReverse(lls);
// ArrayReverse(llTimes);
// ArrayReverse(llIndexes);
//
symbol = _symbol;
period = _period;
_numberOfPivots = _requiredPivots;
_pivotShoulders = _requiredShoulders;
//
result = IsValid();
//
return result;
}
//
// Tools ...
//
// Cleanup ...
void Clean()
{
//
symbol = NULL;
period = NULL;
//
_numberOfPivots = 0;
_pivotShoulders = 0;
//
Clean(higherHighs);
Clean(higherHighTimes);
//
Clean(higherLows);
Clean(higherLowTimes);
//
Clean(lowerHighs);
Clean(lowerHighTimes);
//
Clean(lowerLows);
Clean(lowerLowTimes);
}
//
// Validate ...
bool IsValid()
{
//
bool result = false;
//
result =
//
IsValid(symbol) &&
IsValid(period)
//
;
//
return result;
}
};