145 lines
5 KiB
MQL5
145 lines
5 KiB
MQL5
|
//+------------------------------------------------------------------+
|
||
|
//| ExpertState.mqh |
|
||
|
//| Copyright 2019, Mike Antekov |
|
||
|
//| antekov.yandex.ru |
|
||
|
//+------------------------------------------------------------------+
|
||
|
#property copyright "Copyright 2019, Mike Antekov"
|
||
|
#property link "antekov.yandex.ru"
|
||
|
#property version "1.00"
|
||
|
|
||
|
enum ENUM_TRAILING_STAGE {
|
||
|
TS_INACTIVE,
|
||
|
TS_WAIT_LEVEL,
|
||
|
TS_TRAIL_LEVEL,
|
||
|
TS_REACHED_LEVEL
|
||
|
};
|
||
|
|
||
|
class CTrailing {
|
||
|
private:
|
||
|
ENUM_TRAILING_STAGE m_stage;
|
||
|
string m_name;
|
||
|
double m_valueOpen;
|
||
|
double m_trailOpen;
|
||
|
double m_trailStep;
|
||
|
double m_trailOpenLevel;
|
||
|
bool m_isOpen;
|
||
|
int m_sign;
|
||
|
|
||
|
int waitLevel(double value);
|
||
|
int trailLevel(double value);
|
||
|
public:
|
||
|
CTrailing() : m_stage(TS_INACTIVE) {}
|
||
|
~CTrailing() {}
|
||
|
void Init(double p_valueOpen,
|
||
|
double p_trailOpen,
|
||
|
int p_sign, string p_name = "",
|
||
|
double p_trailStep = 1);
|
||
|
void Deinit() {
|
||
|
m_stage = TS_INACTIVE;
|
||
|
}
|
||
|
int Process(double value);
|
||
|
double Level() {
|
||
|
return m_trailOpenLevel;
|
||
|
}
|
||
|
bool IsInactive() {
|
||
|
return m_stage == TS_INACTIVE;
|
||
|
}
|
||
|
ENUM_TRAILING_STAGE Stage() {
|
||
|
return m_stage;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| |
|
||
|
//+------------------------------------------------------------------+
|
||
|
void CTrailing::Init(double p_valueOpen, double p_trailOpen, int p_sign = 1, string p_name = "", double p_trailStep = 1) {
|
||
|
m_name = p_name;
|
||
|
m_valueOpen = p_valueOpen;
|
||
|
m_trailOpen = p_trailOpen;
|
||
|
m_sign = p_sign;
|
||
|
m_trailStep = p_trailStep;
|
||
|
m_stage = TS_WAIT_LEVEL;
|
||
|
PrintFormat(__FUNCTION__ + ": INIT TRAIL %s (value %s %.0f) | %.0f",
|
||
|
m_name, (m_sign > 0 ? ">" : "<"), m_valueOpen, m_trailOpen);
|
||
|
|
||
|
}
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| |
|
||
|
//+------------------------------------------------------------------+
|
||
|
int CTrailing::Process(double value) {
|
||
|
if(m_stage == TS_WAIT_LEVEL) {
|
||
|
return waitLevel(value);
|
||
|
}
|
||
|
|
||
|
if(m_stage == TS_TRAIL_LEVEL) {
|
||
|
return trailLevel(value);
|
||
|
}
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| |
|
||
|
//+------------------------------------------------------------------+
|
||
|
int CTrailing::waitLevel(double value) {
|
||
|
if (m_sign > 0) {
|
||
|
if (value > m_valueOpen) {
|
||
|
m_stage = TS_TRAIL_LEVEL;
|
||
|
m_trailOpenLevel = value - m_trailOpen;
|
||
|
PrintFormat(__FUNCTION__ + ": SET TRAIL %s: %.0f | %.0f > %.0f",
|
||
|
m_name, m_trailOpenLevel, value, m_valueOpen);
|
||
|
}
|
||
|
} else {
|
||
|
if (value < m_valueOpen) {
|
||
|
m_stage = TS_TRAIL_LEVEL;
|
||
|
m_trailOpenLevel = value + m_trailOpen;
|
||
|
PrintFormat(__FUNCTION__ + ": SET TRAIL %s: %.0f | %.0f < %.0f",
|
||
|
m_name, m_trailOpenLevel, value, m_valueOpen);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| |
|
||
|
//+------------------------------------------------------------------+
|
||
|
int CTrailing::trailLevel(double value) {
|
||
|
if(m_sign > 0) {
|
||
|
if(value < m_trailOpenLevel) {
|
||
|
m_stage = TS_REACHED_LEVEL;
|
||
|
m_trailOpenLevel = value;
|
||
|
PrintFormat(__FUNCTION__ + ": FIRED TRAIL %s: %.0f | %.0f < %.0f",
|
||
|
m_name, m_trailOpenLevel, value, m_trailOpenLevel);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
if (value > m_trailOpenLevel + m_trailOpen + m_trailStep) {
|
||
|
PrintFormat(__FUNCTION__ + ": MOVE TRAIL %s: %.0f -> %.0f | %.0f > %.0f",
|
||
|
m_name, m_trailOpenLevel, value - m_trailOpen,
|
||
|
value, m_trailOpenLevel + m_trailOpen + m_trailStep);
|
||
|
m_trailOpenLevel = value - m_trailOpen;
|
||
|
|
||
|
}
|
||
|
} else {
|
||
|
if(value > m_trailOpenLevel) {
|
||
|
m_stage = TS_REACHED_LEVEL;
|
||
|
m_trailOpenLevel = value;
|
||
|
PrintFormat(__FUNCTION__ + ": FIRED TRAIL %s: %.0f | %.0f > %.0f",
|
||
|
m_name, m_trailOpenLevel, value, m_trailOpenLevel);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
if (value < m_trailOpenLevel - m_trailOpen - m_trailStep) {
|
||
|
PrintFormat(__FUNCTION__ + ": MOVE TRAIL %s: %.0f -> %.0f | %.0f < %.0f",
|
||
|
m_name, m_trailOpenLevel, value + m_trailOpen,
|
||
|
value, m_trailOpenLevel - m_trailOpen - m_trailStep);
|
||
|
m_trailOpenLevel = value + m_trailOpen;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
//+------------------------------------------------------------------+
|