112 lines
3.3 KiB
Plaintext
112 lines
3.3 KiB
Plaintext
|
|
class EntryState {
|
|
public:
|
|
int last_trigger_bar_long;
|
|
int last_trigger_bar_short;
|
|
int last_bl_cross_long;
|
|
int last_bl_cross_short;
|
|
int last_entry_long;
|
|
int last_entry_short;
|
|
|
|
// Constructor
|
|
EntryState() {
|
|
reset();
|
|
}
|
|
|
|
void reset() {
|
|
last_trigger_bar_long = -1000;
|
|
last_trigger_bar_short = -1000;
|
|
last_bl_cross_long = -1000;
|
|
last_bl_cross_short = -1000;
|
|
last_entry_long = -1000;
|
|
last_entry_short = -1000;
|
|
}
|
|
|
|
void update_trigger(bool trig_long, bool trig_short, int curr_bar) {
|
|
if (trig_long) last_trigger_bar_long = curr_bar;
|
|
if (trig_short) last_trigger_bar_short = curr_bar;
|
|
}
|
|
|
|
void update_baseline_cross(int curr_bar, double price, double baseline, double prev_price, double prev_baseline) {
|
|
if (prev_price < prev_baseline && price > baseline)
|
|
last_bl_cross_long = curr_bar;
|
|
if (prev_price > prev_baseline && price < baseline)
|
|
last_bl_cross_short = curr_bar;
|
|
}
|
|
|
|
void update_entry(bool is_long, int curr_bar) {
|
|
if (is_long)
|
|
last_entry_long = curr_bar;
|
|
else
|
|
last_entry_short = curr_bar;
|
|
}
|
|
|
|
int get_last_trigger(bool is_long) {
|
|
return is_long ? last_trigger_bar_long : last_trigger_bar_short;
|
|
}
|
|
|
|
int get_last_cross(bool is_long) {
|
|
return is_long ? last_bl_cross_long : last_bl_cross_short;
|
|
}
|
|
|
|
int get_last_entry(bool is_long) {
|
|
return is_long ? last_entry_long : last_entry_short;
|
|
}
|
|
};
|
|
|
|
// Snapshot of conditions for a potential entry signal
|
|
struct EntryContext {
|
|
bool trigger;
|
|
bool confirm;
|
|
bool volume;
|
|
bool recent;
|
|
bool base_ok;
|
|
bool near;
|
|
bool far;
|
|
int last_entry;
|
|
int last_cross;
|
|
};
|
|
|
|
// Utility: check if signal occurred recently
|
|
bool is_recent(int signal_bar, int curr_bar, int lookback) {
|
|
return (curr_bar - signal_bar) < lookback;
|
|
}
|
|
|
|
// Utility: build current entry condition context
|
|
EntryContext build_entry_context(bool is_long, double price, double baseline, double atr,
|
|
int last_cross, int last_entry,
|
|
bool trigger, bool confirm, bool volume, bool recent) {
|
|
EntryContext ctx;
|
|
ctx.trigger = trigger;
|
|
ctx.confirm = confirm;
|
|
ctx.volume = volume;
|
|
ctx.recent = recent;
|
|
ctx.base_ok = is_long ? (price > baseline) : (price < baseline);
|
|
ctx.near = MathAbs(price - baseline) <= atr;
|
|
ctx.far = MathAbs(price - baseline) > atr;
|
|
ctx.last_entry = last_entry;
|
|
ctx.last_cross = last_cross;
|
|
return ctx;
|
|
}
|
|
|
|
// Class wrapper for entry logic
|
|
class EntryLogic {
|
|
public:
|
|
bool is_standard_entry(const EntryContext &ctx) {
|
|
return ctx.trigger && ctx.confirm && ctx.volume && ctx.recent && ctx.base_ok && ctx.near;
|
|
}
|
|
|
|
bool is_pullback_entry(const EntryContext &ctx, int curr_bar) {
|
|
return (curr_bar - ctx.last_cross <= 2) && ctx.confirm && ctx.volume && ctx.base_ok && ctx.far;
|
|
}
|
|
|
|
bool is_baseline_cross_entry(const EntryContext &ctx, double prev_price, double prev_baseline,double price, double baseline, bool is_long){
|
|
bool crossed = is_long ? (prev_price < prev_baseline && price > baseline): (prev_price > prev_baseline && price < baseline);
|
|
return crossed && ctx.confirm && ctx.volume && ctx.near;
|
|
}
|
|
|
|
bool is_continuation_entry(const EntryContext &ctx, int curr_bar, int look_back) {
|
|
return (curr_bar - ctx.last_entry <= look_back) && ctx.last_entry > ctx.last_cross && ctx.trigger && ctx.confirm && ctx.base_ok;
|
|
}
|
|
};
|