Jeff_Max_Trading/MTLibrary/MTMonitor.mqh

475 lines
15 KiB
MQL5
Raw Permalink Normal View History

2025-05-30 15:02:04 +02:00
//+------------------------------------------------------------------+
//| MTMonitor.mqh |
//| Copyright 2018, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property version "1.10.1"
#include <Generic\Queue.mqh>
#include "MTUtils.mqh"
#include "MTTimer.mqh"
input group "Monitor";
input int positions_box = 10;
input int positions_balancer = 2;
input int long_positions_budget = 5;
input int short_positions_budget = 5;
input double long_volume_budget = 0.3;
input double short_volume_budget = 0.3;
input group "Track Positions"
input int Positions_Counter = 5;
input int winning_closing_trigger = 1000;
input int loosing_closing_trigger = 4000;
input group "Monitor's Timers"
input TimeSlot Balancer_Timer_Step;
input bool BalancerTimerON = true;
input int TimeWindow_Sec = 3600;
input group "Box's Times"
input int Close_All_Hour = 17;; // 5pm , time should be in 00-23 as int
input int Open_All_Hour = 00;; // 12am, time should be in 00-23 int
input bool SweepWhenClosing = false;
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class PositionsTracker
{
private:
int pt_positionsCount;
CQueue<int> pt_ArrayOfPositions;
protected:
int getLastPosition(bool is_long=true);
public:
void Init();
void AddLastPosition(bool is_long=true);
int getPositionsTracker();
int getLastPositionsLong(void);
int getLastPositionsShort(void);
};
//+------------------------------------------------------------------+
int PositionsTracker::getLastPositionsLong(void)
{
int result = getLastPosition(true);
if(result == 0)
{
return 1;
}
return result;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int PositionsTracker::getLastPositionsShort(void)
{
int result = getLastPosition(false);
if(result == 0)
{
return 1;
}
return result;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void PositionsTracker::Init(void)
{
pt_positionsCount = Positions_Counter;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
int PositionsTracker::getLastPosition(bool is_long=true)
{
int long_count = 0;
int short_count = 0;
int temp = -1;
int pt_Size = pt_ArrayOfPositions.Count();
for(int i=pt_Size; i > 0; i--)
{
temp = pt_ArrayOfPositions.Dequeue();
if(temp == 1)
{
long_count++;
}
else
if(temp == 0)
{
short_count ++;
}
pt_ArrayOfPositions.Enqueue(temp);
}
if(is_long)
{
return long_count;
}
return short_count;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void PositionsTracker::AddLastPosition(bool is_long=true)
{
if(is_long)
{
pt_ArrayOfPositions.Enqueue(1);
}
else
{
pt_ArrayOfPositions.Enqueue(0);
}
int pt_Size = pt_ArrayOfPositions.Count();
if(pt_Size > pt_positionsCount)
{
pt_ArrayOfPositions.Dequeue();
}
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class MTMonitor
{
private:
int long_pBudget;
int short_pBudget;
int leverage;
int p_positions_budget;
int p_positions_balancer;
int p_winning_closing_trigger;
int p_cushion;
int p_capital;
double p_win_percent;
double initial_equity;
double LS_ratio;
double long_vBudget;
double short_vBudget;
bool p_balancer_window_open;
bool p_agent_window_open;
PositionsTracker p_position_tracker;
MTTimer closing_timer;
MTTimer opening_timer;
public:
double MTMonitor::GetMaximumVolumePossible(void);
void MTMonitor::CloseAllWhenWhining(void);
void MTMonitor::Init(void);
bool MTMonitor::BoxCanPlacePosition(void);
bool MTMonitor::BalancerCanPlacePosition(void);
void MTMonitor::AssessClosingLimits(void);
void MTMonitor::CloseAllWhenLosing(void);
bool MTMonitor::CanPlacePositionInDirection(bool isLong=true);
void MTMonitor::ResetEquity(void) {initial_equity = AccountInfoDouble(ACCOUNT_EQUITY); };
void MTMonitor::addPositionToTracker(bool is_long=true) { p_position_tracker.AddLastPosition(is_long); };
PositionsTracker* MTMonitor::getPositionTracker(void) { return &p_position_tracker; };
void MTMonitor::UpdateClosingTimer(void);
void MTMonitor::UpdateOpeningTimer(void);
void MTMonitor::UpdatePositionsAgentTimers(void);
bool MTMonitor::IsBalancerWindowOpen() { return p_balancer_window_open; };
bool MTMonitor::IsAgentWindowOpen() { return p_agent_window_open; };
bool MTMonitor::CanPlacePositionInDirectionByVolume(bool isLong=true);
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void MTMonitor::Init()
{
p_positions_balancer = positions_balancer;
p_positions_budget = positions_box;
p_winning_closing_trigger = winning_closing_trigger;
initial_equity = AccountInfoDouble(ACCOUNT_EQUITY);
p_cushion = 0;
p_capital = 0;
p_win_percent = 0;
LS_ratio = 0;
leverage = 0;
long_pBudget = long_positions_budget;
long_vBudget = long_volume_budget;
short_pBudget = short_positions_budget;
short_vBudget = short_volume_budget;
p_position_tracker.Init();
// Possible correction to enact diff object references
datetime wall_init_time = TimeCurrent();
opening_timer = new MTTimer(wall_init_time);
closing_timer = new MTTimer(wall_init_time+TimeWindow_Sec);
p_agent_window_open = false;
p_balancer_window_open = false;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void MTMonitor::UpdateClosingTimer()
{
if(closing_timer.has_set_alert())
{
if(closing_timer.has_triggered())
{
p_balancer_window_open = false;
closing_timer.reset_alert_set();
closing_timer.roll_base_time();
}
}
else
{
switch(Balancer_Timer_Step)
{
case TS_every_4_hrs:
closing_timer.set_alert_from_base_4hrs();
break;
case TS_every_12_hrs:
closing_timer.set_alert_from_base_12hrs();
break;
case TS_every_24_hrs:
closing_timer.set_alert_from_base_24hrs();
break;
default:
Print("No Timer Set : Closing");
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void MTMonitor::UpdateOpeningTimer()
{
if(opening_timer.has_set_alert())
{
if(opening_timer.has_triggered())
{
p_balancer_window_open = true;
opening_timer.reset_alert_set();
opening_timer.roll_base_time();
}
}
else
{
switch(Balancer_Timer_Step)
{
case TS_every_4_hrs:
opening_timer.set_alert_from_base_4hrs();
break;
case TS_every_12_hrs:
opening_timer.set_alert_from_base_12hrs();
break;
case TS_every_24_hrs:
opening_timer.set_alert_from_base_24hrs();
break;
default:
Print("No Timer Set: Opening");
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double MTMonitor::GetMaximumVolumePossible(void)
{
double capital_distributed = p_capital / LS_ratio;
double capital_per_direction = capital_distributed * leverage;
return (capital_per_direction*PRICE);
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool MTMonitor::BalancerCanPlacePosition(void)
{
// Timers need to be updated in here to open/close the window correctly
UpdateOpeningTimer();
UpdateClosingTimer();
// Positions Budget Check that allows to determine if slots avail for positions
int open_positions = PositionsTotal();
int total_position_budget = p_positions_budget + p_positions_balancer;
int actionable_difference = total_position_budget - open_positions;
if(BalancerTimerON)
{
bool window = IsBalancerWindowOpen();
if(window)
{
int check = 1;
}
return (actionable_difference > 0 && window);
}
else
{
return (actionable_difference > 0);
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool MTMonitor::BoxCanPlacePosition(void)
{
if(!IsAgentWindowOpen())
{
return false;
}
int open_positions = PositionsTotal();
int actionable_difference = (p_positions_budget) - open_positions;
return actionable_difference > 0;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void MTMonitor::CloseAllWhenWhining(void)
{
double profit = AccountInfoDouble(ACCOUNT_EQUITY)- initial_equity;
if(profit >= winning_closing_trigger && profit > 0)
{
close_all_positions();
MTMonitor::ResetEquity();
}
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void MTMonitor::CloseAllWhenLosing(void)
{
double profit = initial_equity - AccountInfoDouble(ACCOUNT_EQUITY);
if(profit >= loosing_closing_trigger && profit > 0)
{
close_all_positions();
MTMonitor::ResetEquity();
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void MTMonitor::AssessClosingLimits(void)
{
MTMonitor::CloseAllWhenLosing();
MTMonitor::CloseAllWhenWhining();
MTMonitor::UpdatePositionsAgentTimers();
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool MTMonitor::CanPlacePositionInDirection(bool isLong=true)
{
if(isLong)
{
return CountPositionsByType(isLong) < long_pBudget;
}
else
{
return (CountPositionsByType(isLong) < short_pBudget);
}
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool MTMonitor::CanPlacePositionInDirectionByVolume(bool isLong=true)
{
if(isLong)
{
return GetVolumeInLong() < long_vBudget;
}
else
{
return GetVolumeInShort() < short_vBudget;
}
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void MTMonitor::UpdatePositionsAgentTimers()
{
int closing_set_hour = Close_All_Hour;
int opening_set_hour = Open_All_Hour;
MqlDateTime current_time;
TimeCurrent(current_time);
if(current_time.hour == closing_set_hour && PositionsTotal() > 0)
{
if(SweepWhenClosing)
{
close_all_positions();
}
p_agent_window_open = false;
}
else
if(current_time.hour >= opening_set_hour && current_time.hour < closing_set_hour)
{
p_agent_window_open = true;
}
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+