475 lines
15 KiB
MQL5
475 lines
15 KiB
MQL5
|
//+------------------------------------------------------------------+
|
||
|
//| 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;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
|
||
|
//+------------------------------------------------------------------+
|