//+------------------------------------------------------------------+ //| MTBalancer.mqh | //| Copyright 2018, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property version "1.3.2" #include "MTUtils.mqh" enum BalancerTrigger { mtb_position = 0, mtb_volume = 1 }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class MTBalancer { public: BalancerTrigger balancer_type; int positions_trigger; double volume_difference; bool enable_trade_on_limit; protected: double base_volume; double balancing_volume; public: void setBaseVolume(double ibase_volume=0.1) {base_volume = ibase_volume;} void setBalancingVolume(double balance) {balancing_volume = balance;}; void doBalancing(double ask,double bid,int take_profit); void doBalancingByPositions(double ask,double bid,int take_profit); void doBalancingByVolume(double ask,double bid,double take_profit); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void MTBalancer::doBalancing(double ask, double bid, int take_profit) { //uint count_pos = PositionsTotal(); //if(count_pos == 0) // { // /*This is a safeguard for not "early stage" trading sessions */ // return; // } switch(balancer_type) { case mtb_volume: if(GetVolumeDifference() >= volume_difference) { doBalancingByVolume(ask,bid,take_profit); } break; case mtb_position: if(PositionDifferenceByType() > positions_trigger) { doBalancingByPositions(ask,bid,take_profit); } break; default: break; } } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void MTBalancer::doBalancingByVolume(double ask,double bid,double take_profit) { double top_edge = GetHigestPositionOpenPrice(); /*This needs to be check for error (-1)*/ double bottom_edge = GetLowestPositionOpenPrice(); /*This needs to be check for error (-1)*/ if(((ask >= top_edge) || (!enable_trade_on_limit)) && (GetVolumeDifference(true) < 0)) { int current_difference = fabs(GetVolumeDifference()/base_volume); int unbalancer_value = fabs(balancing_volume/base_volume); place_a_long(ask, take_profit, current_difference + unbalancer_value); } if(((bid <= bottom_edge) || (!enable_trade_on_limit)) && (GetVolumeDifference(true) > 0)) { int current_difference = fabs(GetVolumeDifference()/base_volume); int unbalancer_value = fabs(balancing_volume/base_volume); place_a_short(bid,take_profit, current_difference + unbalancer_value); } } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void MTBalancer::doBalancingByPositions(double ask,double bid,int take_profit) { double top_edge = GetHigestPositionOpenPrice(); double bottom_edge = GetLowestPositionOpenPrice(); int position_difference = PositionDifferenceByType(true); if((ask >= top_edge) && (position_difference>0)) { place_a_long(ASK, take_profit); } else if((bid <= bottom_edge) && (position_difference < 0)) { place_a_short(BID, take_profit); } } //+------------------------------------------------------------------+