183 lines
7.2 KiB
MQL5
183 lines
7.2 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| TrailingStop.mq5 |
|
|
//| Copyright 2022, MetaQuotes Ltd. |
|
|
//| https://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "2022, MetaQuotes Ltd."
|
|
#property link "https://www.mql5.com"
|
|
#property description "Open new position with minimal lot on current symbol (if not exist), then monitor and move stop loss according to specified or daily range."
|
|
|
|
#define SHOW_WARNINGS // output extended info into the log, with changes in data state
|
|
#define WARNING Print // use simple Print for warnings (instead of a built-in format with line numbers etc.)
|
|
#include "..\..\Include\MqlTradeSync.mqh"
|
|
#include "..\..\Include\AutoPtr.mqh"
|
|
#include "..\..\Include\TrailingStop.mqh"
|
|
|
|
enum ENUM_ORDER_TYPE_MARKET
|
|
{
|
|
MARKET_BUY = ORDER_TYPE_BUY, // ORDER_TYPE_BUY
|
|
MARKET_SELL = ORDER_TYPE_SELL // ORDER_TYPE_SELL
|
|
};
|
|
|
|
input int TrailingDistance = 0; // Distance to Stop Loss in points (0 = autodetect)
|
|
input int TrailingStep = 10; // Trailing Step in points
|
|
input int MATrailingPeriod = 0; // Period for Trailing by MA (0 = disabled)
|
|
input ENUM_ORDER_TYPE_MARKET Type;
|
|
input string Comment;
|
|
input ulong Deviation;
|
|
input ulong Magic = 1234567890;
|
|
|
|
AutoPtr<TrailingStop> tr;
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert initialization function |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
if(AccountInfoInteger(ACCOUNT_TRADE_MODE) != ACCOUNT_TRADE_MODE_DEMO)
|
|
{
|
|
Alert("This is a test EA! Run it on a DEMO account only!");
|
|
return INIT_FAILED;
|
|
}
|
|
return INIT_SUCCEEDED;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Helper function to find a compatible position |
|
|
//+------------------------------------------------------------------+
|
|
bool GetMyPosition(const string s, const ulong m)
|
|
{
|
|
for(int i = 0; i < PositionsTotal(); ++i)
|
|
{
|
|
if(PositionGetSymbol(i) == s && PositionGetInteger(POSITION_MAGIC) == m)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Prepare MqlTradeRequestSync struct, send it to create a position |
|
|
//+------------------------------------------------------------------+
|
|
ulong OpenPosition()
|
|
{
|
|
// define the struct
|
|
MqlTradeRequestSync request;
|
|
|
|
// default values
|
|
const bool wantToBuy = Type == MARKET_BUY;
|
|
const double volume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
|
|
|
|
// fill optional fields of the struct
|
|
request.magic = Magic;
|
|
request.deviation = Deviation;
|
|
request.comment = Comment;
|
|
|
|
ResetLastError();
|
|
// execute a trade and wait its completion
|
|
if((bool)(wantToBuy ? request.buy(volume) : request.sell(volume))
|
|
&& request.completed())
|
|
{
|
|
Print("OK Order/Deal/Position");
|
|
}
|
|
|
|
return request.position;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Start trailing existing position or create a new one |
|
|
//+------------------------------------------------------------------+
|
|
void Setup()
|
|
{
|
|
int distance = 0;
|
|
const double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
|
|
|
|
if(MATrailingPeriod == 0)
|
|
{
|
|
if(TrailingDistance == 0) // autodetect daily range
|
|
{
|
|
distance = (int)((iHigh(_Symbol, PERIOD_D1, 1) - iLow(_Symbol, PERIOD_D1, 1))
|
|
/ point / 2);
|
|
Print("Autodetected daily distance (points): ", distance);
|
|
}
|
|
else
|
|
{
|
|
distance = TrailingDistance;
|
|
}
|
|
}
|
|
|
|
// only process positions on current symbol and our magic id
|
|
if(GetMyPosition(_Symbol, Magic))
|
|
{
|
|
const ulong ticket = PositionGetInteger(POSITION_TICKET);
|
|
Print("The next position found: ", ticket);
|
|
tr = MATrailingPeriod > 0 ?
|
|
new TrailingStopByMA(ticket, MATrailingPeriod) :
|
|
new TrailingStop(ticket, distance, TrailingStep);
|
|
}
|
|
else // no our position
|
|
{
|
|
Print("No positions found, lets open it...");
|
|
const ulong ticket = OpenPosition();
|
|
if(ticket)
|
|
{
|
|
tr = MATrailingPeriod > 0 ?
|
|
new TrailingStopByMA(ticket, MATrailingPeriod) :
|
|
new TrailingStop(ticket, distance, TrailingStep);
|
|
}
|
|
}
|
|
|
|
if(tr[] != NULL)
|
|
{
|
|
tr[].trail(); // 1-st time trail after position creation or acqusition
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert tick function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTick()
|
|
{
|
|
if(tr[] == NULL || !tr[].trail())
|
|
{
|
|
// if there is no tracked position yet, create it or find among existing
|
|
Setup();
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
/*
|
|
example output (default settings, tester)
|
|
|
|
2022.01.10 00:02:00 Autodetected daily distance (points): 373
|
|
2022.01.10 00:02:00 No positions found, lets open it...
|
|
2022.01.10 00:02:00 instant buy 0.01 EURUSD at 1.13612 (1.13550 / 1.13612 / 1.13550)
|
|
2022.01.10 00:02:00 deal #2 buy 0.01 EURUSD at 1.13612 done (based on order #2)
|
|
2022.01.10 00:02:00 deal performed [#2 buy 0.01 EURUSD at 1.13612]
|
|
2022.01.10 00:02:00 order performed buy 0.01 at 1.13612 [#2 buy 0.01 EURUSD at 1.13612]
|
|
2022.01.10 00:02:00 Waiting for position for deal D=2
|
|
2022.01.10 00:02:00 OK Order/Deal/Position
|
|
2022.01.10 00:02:00 Initial SL: 1.131770
|
|
2022.01.10 00:02:00 position modified [#2 buy 0.01 EURUSD 1.13612 sl: 1.13177]
|
|
2022.01.10 00:02:00 OK Trailing: 1.13177
|
|
2022.01.10 00:06:13 SL: 1.131770 -> 1.131880
|
|
2022.01.10 00:06:13 position modified [#2 buy 0.01 EURUSD 1.13612 sl: 1.13188]
|
|
2022.01.10 00:06:13 OK Trailing: 1.13188
|
|
2022.01.10 00:09:17 SL: 1.131880 -> 1.131990
|
|
2022.01.10 00:09:17 position modified [#2 buy 0.01 EURUSD 1.13612 sl: 1.13199]
|
|
2022.01.10 00:09:17 OK Trailing: 1.13199
|
|
2022.01.10 00:09:26 SL: 1.131990 -> 1.132110
|
|
2022.01.10 00:09:26 position modified [#2 buy 0.01 EURUSD 1.13612 sl: 1.13211]
|
|
2022.01.10 00:09:26 OK Trailing: 1.13211
|
|
2022.01.10 00:09:35 SL: 1.132110 -> 1.132240
|
|
2022.01.10 00:09:35 position modified [#2 buy 0.01 EURUSD 1.13612 sl: 1.13224]
|
|
2022.01.10 00:09:35 OK Trailing: 1.13224
|
|
2022.01.10 10:06:38 stop loss triggered #2 buy 0.01 EURUSD 1.13612 sl: 1.13224 [#3 sell 0.01 EURUSD at 1.13224]
|
|
2022.01.10 10:06:38 deal #3 sell 0.01 EURUSD at 1.13221 done (based on order #3)
|
|
2022.01.10 10:06:38 deal performed [#3 sell 0.01 EURUSD at 1.13221]
|
|
2022.01.10 10:06:38 order performed sell 0.01 at 1.13221 [#3 sell 0.01 EURUSD at 1.13224]
|
|
2022.01.10 10:06:38 Autodetected daily distance (points): 373
|
|
2022.01.10 10:06:38 No positions found, lets open it...
|
|
|
|
*/
|
|
//+------------------------------------------------------------------+
|