187 lines
18 KiB
Plaintext
187 lines
18 KiB
Plaintext
|
|
//+------------------------------------------------------------------+
|
|||
|
|
//| Impulse 2.0.mqh |
|
|||
|
|
//| Copyright 2016, Vasiliy Sokolov, St-Petersburg, Russia |
|
|||
|
|
//| https://www.mql5.com/en/users/c-4 |
|
|||
|
|
//+------------------------------------------------------------------+
|
|||
|
|
#property copyright "Copyright 2016, Vasiliy Sokolov."
|
|||
|
|
#property link "https://www.mql5.com/en/users/c-4"
|
|||
|
|
#include "Strategy\Strategy.mqh"
|
|||
|
|
#include "Strategy\Indicators.mqh"
|
|||
|
|
|
|||
|
|
input int PeriodMA = 12;
|
|||
|
|
input double StopPercent = 0.05;
|
|||
|
|
|
|||
|
|
//+------------------------------------------------------------------+
|
|||
|
|
//| The CImpulse Strategy |
|
|||
|
|
//+------------------------------------------------------------------+
|
|||
|
|
class CImpulse : public CStrategy
|
|||
|
|
{
|
|||
|
|
private:
|
|||
|
|
double m_percent; // Percent value for the level of a pending order
|
|||
|
|
protected:
|
|||
|
|
virtual void InitBuy(const MarketEvent &event);
|
|||
|
|
virtual void InitSell(const MarketEvent &event);
|
|||
|
|
virtual void SupportBuy(const MarketEvent &event,CPosition *pos);
|
|||
|
|
virtual void SupportSell(const MarketEvent &event,CPosition *pos);
|
|||
|
|
virtual void SupportPendingBuy(const MarketEvent &event,CPendingOrder *order);
|
|||
|
|
virtual void SupportPendingSell(const MarketEvent &event,CPendingOrder* order);
|
|||
|
|
virtual bool OnInit(void);
|
|||
|
|
public:
|
|||
|
|
double GetPercent(void);
|
|||
|
|
void SetPercent(double percent);
|
|||
|
|
CUnIndicator UnMA;
|
|||
|
|
};
|
|||
|
|
//+------------------------------------------------------------------+
|
|||
|
|
//| Initialize the moving average |
|
|||
|
|
//+------------------------------------------------------------------+
|
|||
|
|
bool CImpulse::OnInit(void)
|
|||
|
|
{
|
|||
|
|
UnMA.SetParameter(12);
|
|||
|
|
UnMA.SetParameter(0);
|
|||
|
|
UnMA.SetParameter(MODE_SMA);
|
|||
|
|
UnMA.SetParameter(PRICE_CLOSE);
|
|||
|
|
m_percent = StopPercent;
|
|||
|
|
if(UnMA.Create(Symbol(), Period(), IND_MA) != INVALID_HANDLE)
|
|||
|
|
return true;
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
//+------------------------------------------------------------------+
|
|||
|
|
//| Placing pending BuyStop orders |
|
|||
|
|
//+------------------------------------------------------------------+
|
|||
|
|
void CImpulse::InitBuy(const MarketEvent &event)
|
|||
|
|
{
|
|||
|
|
if(!IsTrackEvents(event))return; // Create pending only at the opening of a new bar
|
|||
|
|
if(PositionsTotal(POSITION_TYPE_BUY, ExpertSymbol(), ExpertMagic()) > 0) // There must be no open long positions present
|
|||
|
|
return;
|
|||
|
|
if(OrdersTotal(POSITION_TYPE_BUY, ExpertSymbol(), ExpertMagic()) > 0) // There must be no pending buy order present
|
|||
|
|
return;
|
|||
|
|
double target = WS.Ask() + WS.Ask()*(m_percent/100.0); // Calculate the level of the new pending order
|
|||
|
|
if(target < UnMA[0]) // The order trigger price must be above the Moving Average
|
|||
|
|
return;
|
|||
|
|
Trade.BuyStop(MM.GetLotFixed(), target, ExpertSymbol(), 0, 0, NULL); // Place the new BuyStop order
|
|||
|
|
}
|
|||
|
|
//+------------------------------------------------------------------+
|
|||
|
|
//| Working with the pending BuyStop orders for opening a long |
|
|||
|
|
//| position |
|
|||
|
|
//+------------------------------------------------------------------+
|
|||
|
|
void CImpulse::SupportPendingBuy(const MarketEvent &event,CPendingOrder *order)
|
|||
|
|
{
|
|||
|
|
if(!IsTrackEvents(event))return;
|
|||
|
|
double target = WS.Ask() + WS.Ask()*(m_percent/100.0); // Calculate the level of the new pending order
|
|||
|
|
if(UnMA[0] > target) // If the new level is lower than the current Moving Average
|
|||
|
|
order.Delete(); // - lete it
|
|||
|
|
else // Otherwise, modify it with the new price
|
|||
|
|
order.Modify(target);
|
|||
|
|
}
|
|||
|
|
//+------------------------------------------------------------------+
|
|||
|
|
//| Working with the pending SellStop orders for opening a short |
|
|||
|
|
//| position |
|
|||
|
|
//+------------------------------------------------------------------+
|
|||
|
|
void CImpulse::SupportPendingSell(const MarketEvent &event,CPendingOrder* order)
|
|||
|
|
{
|
|||
|
|
if(!IsTrackEvents(event))return;
|
|||
|
|
double target = WS.Ask() - WS.Ask()*(m_percent/100.0); // Calculate the level of the new pending order
|
|||
|
|
if(UnMA[0] < target) // If the new level is higher than the current Moving Average
|
|||
|
|
order.Delete(); // - lete it
|
|||
|
|
else // Otherwise, modify it with the new price
|
|||
|
|
order.Modify(target);
|
|||
|
|
}
|
|||
|
|
//+------------------------------------------------------------------+
|
|||
|
|
//| Placing pending SellStop orders |
|
|||
|
|
//+------------------------------------------------------------------+
|
|||
|
|
void CImpulse::InitSell(const MarketEvent &event)
|
|||
|
|
{
|
|||
|
|
if(!IsTrackEvents(event))return; // Create pending only at the opening of a new bar
|
|||
|
|
if(PositionsTotal(POSITION_TYPE_SELL, ExpertSymbol(), ExpertMagic()) > 0) // There must be no open short positions present
|
|||
|
|
return;
|
|||
|
|
if(OrdersTotal(POSITION_TYPE_SELL, ExpertSymbol(), ExpertMagic()) > 0) // There must be no pending sell order present
|
|||
|
|
return;
|
|||
|
|
double target = WS.Bid() - WS.Bid()*(m_percent/100.0); // Calculate the level of the new pending order
|
|||
|
|
if(target > UnMA[0]) // The order trigger price must be below the Moving Average
|
|||
|
|
return;
|
|||
|
|
Trade.SellStop(MM.GetLotFixed(), target, ExpertSymbol(), 0, 0, NULL); // Place the new BuyStop order
|
|||
|
|
}
|
|||
|
|
//+------------------------------------------------------------------+
|
|||
|
|
//| Managing a long position in accordance with the Moving Average |
|
|||
|
|
//+------------------------------------------------------------------+
|
|||
|
|
void CImpulse::SupportBuy(const MarketEvent &event,CPosition *pos)
|
|||
|
|
{
|
|||
|
|
int bar_open = WS.IndexByTime(pos.TimeOpen());
|
|||
|
|
if(!IsTrackEvents(event))return;
|
|||
|
|
ENUM_ACCOUNT_MARGIN_MODE mode = (ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE);
|
|||
|
|
if(mode != ACCOUNT_MARGIN_MODE_RETAIL_HEDGING)
|
|||
|
|
{
|
|||
|
|
double target = WS.Bid() - WS.Bid()*(m_percent/100.0);
|
|||
|
|
if(target < UnMA[0])
|
|||
|
|
pos.StopLossValue(target);
|
|||
|
|
else
|
|||
|
|
pos.StopLossValue(0.0);
|
|||
|
|
}
|
|||
|
|
if(WS.Bid() < UnMA[0])
|
|||
|
|
pos.CloseAtMarket();
|
|||
|
|
}
|
|||
|
|
//+------------------------------------------------------------------+
|
|||
|
|
//| Managing a short position in accordance with the Moving Average |
|
|||
|
|
//+------------------------------------------------------------------+
|
|||
|
|
void CImpulse::SupportSell(const MarketEvent &event,CPosition *pos)
|
|||
|
|
{
|
|||
|
|
if(!IsTrackEvents(event))return;
|
|||
|
|
ENUM_ACCOUNT_MARGIN_MODE mode = (ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE);
|
|||
|
|
if(mode != ACCOUNT_MARGIN_MODE_RETAIL_HEDGING)
|
|||
|
|
{
|
|||
|
|
double target = WS.Ask() + WS.Ask()*(m_percent/100.0);
|
|||
|
|
if(target > UnMA[0])
|
|||
|
|
pos.StopLossValue(target);
|
|||
|
|
else
|
|||
|
|
pos.StopLossValue(0.0);
|
|||
|
|
}
|
|||
|
|
if(WS.Ask() > UnMA[0])
|
|||
|
|
pos.CloseAtMarket();
|
|||
|
|
}
|
|||
|
|
//+------------------------------------------------------------------+
|
|||
|
|
//| Returns the percent of the breakthrough level |
|
|||
|
|
//+------------------------------------------------------------------+
|
|||
|
|
double CImpulse::GetPercent(void)
|
|||
|
|
{
|
|||
|
|
return m_percent;
|
|||
|
|
}
|
|||
|
|
//+------------------------------------------------------------------+
|
|||
|
|
//| Sets percent of the breakthrough level |
|
|||
|
|
//+------------------------------------------------------------------+
|
|||
|
|
void CImpulse::SetPercent(double percent)
|
|||
|
|
{
|
|||
|
|
m_percent = percent;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//+------------------------------------------------------------------+
|
|||
|
|
//| Expert initialization function |
|
|||
|
|
//+------------------------------------------------------------------+
|
|||
|
|
int OnInit()
|
|||
|
|
{
|
|||
|
|
CImpulse* impulse = new CImpulse();
|
|||
|
|
impulse.ExpertMagic(140578);
|
|||
|
|
impulse.ExpertName("Impulse 2.0");
|
|||
|
|
impulse.Timeframe(Period());
|
|||
|
|
impulse.ExpertSymbol(Symbol());
|
|||
|
|
Manager.AddStrategy(impulse);
|
|||
|
|
return(INIT_SUCCEEDED);
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
//+------------------------------------------------------------------+
|
|||
|
|
//| Expert tick function |
|
|||
|
|
//+------------------------------------------------------------------+
|
|||
|
|
void OnTick()
|
|||
|
|
{
|
|||
|
|
Manager.OnTick();
|
|||
|
|
}
|
|||
|
|
//+------------------------------------------------------------------+
|
|||
|
|
//| ChartEvent function |
|
|||
|
|
//+------------------------------------------------------------------+
|
|||
|
|
void OnChartEvent(const int id,
|
|||
|
|
const long &lparam,
|
|||
|
|
const double &dparam,
|
|||
|
|
const string &sparam)
|
|||
|
|
{
|
|||
|
|
Manager.OnChartEvent(id, lparam, dparam, sparam);
|
|||
|
|
ChartRedraw(0);
|
|||
|
|
}�
|