Price Data Components
Orders Execution
Indicators Used
Miscellaneous
2
Views
0
Downloads
0
Favorites
RangeBreakout
#property copyright "Mokara"
#property link "https://www.mql5.com/en/users/mokara"
#property description "Periodic Range Breakout"
#property version "1.0"
#property script_show_inputs true
#define ATR_BUFFER 2
enum ENUM_HOUR
{
H00 = 0, H01, H02, H03, H04, H05, H06, H07, H08, H09, H10, H11, H12,
H13, H14, H15, H16, H17, H18, H19, H20, H21, H22, H23
};
enum ENUM_PHASE
{
STANDBY,
SETUP,
TRADE
};
input ENUM_DAY_OF_WEEK inDay = MONDAY; //Day of Week
input ENUM_HOUR inHour = H00; //Starting Hour
input double inPerPrice = 1; //Price Percentage (0.3%-3%)
input double inPerATR = 100; //ATR Percentage (10%-200%)
input double inPerProfit = 100; //Take Profit Percentage (10%-200%)
input double inPerLoss = 100; //Stop Loss Percentage (10%-200%)
input double inLot = 0.1; //Lot
ENUM_DAY_OF_WEEK Day;
ENUM_HOUR Hour;
ENUM_PHASE Phase;
MqlTradeRequest tReq;
MqlTradeResult tRes;
MqlDateTime dtCurrent;
double perPrice;
double perATR;
double perProfit;
double perLoss;
double Range;
double Profit;
double Loss;
double cumLoss; //cumulative loss
double comLoss; //loss compensation
double pCurAsk;
double pCurBid;
double pCenter;
double pHighStop;
double pLowStop;
double pHighProfit;
double pLowProfit;
double pHighLoss;
double pLowLoss;
double Lot;
double arrayATR[];
ulong orderTicket;
uint countSetup = 0;
int handleATR = 0;
int kLot = 1;
bool isSet = false;
bool doCalc = false;
bool tradeOpen = false;
void CheckInputs()
{
if(inDay == SATURDAY || inDay == SUNDAY)
{
Alert("WARNING: weekend day. taking Monday as default.");
Day = MONDAY;
}
else
{
Day = inDay;
}
if(inPerPrice < 0.3 || inPerPrice > 3)
{
Alert("WARNING: invalid price percentage. taking 1 as default.");
perPrice = 1;
}
else
{
perPrice = inPerPrice;
}
if(inPerATR < 10 || inPerATR > 200)
{
Alert("WARNING: invalid atr percentage. taking 100 as default.");
perATR = 100;
}
else
{
perATR = inPerATR;
}
if(inPerProfit < 10 || inPerProfit > 200)
{
Alert("WARNING: invalid profit percentage. taking 100 as default.");
perProfit = 100;
}
else
{
perProfit = inPerProfit;
}
if(inPerLoss < 10 || inPerLoss > 200)
{
Alert("WARNING: invalid loss percentage. taking 100 as default.");
perLoss = 100;
}
else
{
perLoss = inPerLoss;
}
}
bool Initialization()
{
Phase = STANDBY;
isSet = false;
handleATR = iATR(_Symbol, PERIOD_D1, 20);
if(handleATR == INVALID_HANDLE)
{
Alert("ERROR: unable to get handle for atr.");
return(false);
}
return(true);
}
void SetVolume()
{
double volMin = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
double volMax = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
double volStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
int ratio = (int)MathRound(inLot / volStep);
if(inLot < volMin) Lot = volMin;
else if(inLot > volMax) Lot = volMax;
else if(MathAbs(ratio * volStep - inLot) > 0.0000001) Lot = ratio * volStep;
else Lot = inLot;
}
void Calculate()
{
if(CopyBuffer(handleATR, 0, 0, ATR_BUFFER, arrayATR) != ATR_BUFFER)
{
Alert("ERROR: unable to copy atr buffer. using price percentage instead.");
Range = NormalizeDouble(pCurAsk * perPrice / 100, _Digits);
}
else
{
Range = NormalizeDouble(arrayATR[1] * perATR / 100, _Digits);
}
Profit = NormalizeDouble((Range * perProfit / 100), _Digits);
Loss = NormalizeDouble(Range * perLoss / 100, _Digits);
if(comLoss != 0) {Profit = comLoss; Loss += comLoss;}
pHighStop = pCenter + Range;
pHighProfit = pHighStop + Profit;
pHighLoss = pHighStop - Loss;
pLowStop = pCenter - Range;
pLowProfit = pLowStop - Profit;
pLowLoss = pLowStop + Loss;
}
void Martingale()
{
if(HistoryDealSelect(orderTicket + 1))
{
if(HistoryDealGetDouble(orderTicket + 1, DEAL_PROFIT) < 0)
{
kLot *= 2;
cumLoss += HistoryDealGetDouble(orderTicket + 1, DEAL_PROFIT);
comLoss = MathAbs(NormalizeDouble(cumLoss * _Point * 10 / (kLot * SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE)), _Digits));
}
else
{
kLot = 1;
cumLoss = 0;
comLoss = 0;
}
}
}
bool OpenBuy()
{
ZeroMemory(tReq);
ZeroMemory(tRes);
tReq.symbol = _Symbol;
tReq.volume = Lot * kLot;
tReq.action = TRADE_ACTION_DEAL;
tReq.deviation = 20;
tReq.type = ORDER_TYPE_BUY;
tReq.price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
tReq.tp = pHighProfit;
tReq.sl = pHighLoss;
if(!OrderSend(tReq, tRes)) return(false);
tradeOpen = true;
orderTicket = tRes.order;
return(true);
}
bool OpenSell()
{
ZeroMemory(tReq);
ZeroMemory(tRes);
tReq.symbol = _Symbol;
tReq.volume = Lot * kLot;
tReq.action = TRADE_ACTION_DEAL;
tReq.deviation = 20;
tReq.type = ORDER_TYPE_SELL;
tReq.price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
tReq.tp = pLowProfit;
tReq.sl = pLowLoss;
if(!OrderSend(tReq, tRes)) return(false);
tradeOpen = true;
orderTicket = tRes.order;
return(true);
}
void DrawVLine(string n, int c, int s, datetime x)
{
if(ObjectFind(0, n) == 0) ObjectDelete(0, n);
ObjectCreate(0, n, OBJ_VLINE, 0, x, 0);
ObjectSetInteger(0, n, OBJPROP_COLOR, c);
ObjectSetInteger(0, n, OBJPROP_STYLE, s);
}
int OnInit()
{
CheckInputs();
SetVolume();
if(!Initialization())
{
return(INIT_FAILED);
}
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
}
void OnTick()
{
pCurAsk = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
pCurBid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
if(Phase == STANDBY)
{
ZeroMemory(dtCurrent);
TimeToStruct(TimeCurrent(), dtCurrent);
if(isSet == false && dtCurrent.day_of_week == Day && dtCurrent.hour == (Hour + 1))
{
pCenter = iClose(_Symbol, PERIOD_H1, 1);
Martingale();
Calculate();
isSet = true;
DrawVLine("Start_" + (string)countSetup, clrAqua, STYLE_DOT, TimeCurrent());
countSetup++;
Phase = SETUP;
return;
}
}
if(Phase == SETUP)
{
if(pCurAsk > pHighStop && tradeOpen == false)
{
if(AccountInfoDouble(ACCOUNT_MARGIN_FREE) < (1000 * Lot))
{
Alert("We have no money. Free Margin = ", AccountInfoDouble(ACCOUNT_MARGIN_FREE));
return;
}
if(OpenBuy())
{
Alert("INFO: buy order opened. ");
Phase = TRADE;
}
else
{
Alert("ERROR: buy order cannot be opened. ");
return;
}
}
if(pCurBid < pLowStop && tradeOpen == false)
{
if(AccountInfoDouble(ACCOUNT_MARGIN_FREE) < (1000 * Lot))
{
Alert("We have no money. Free Margin = ", AccountInfoDouble(ACCOUNT_MARGIN_FREE));
return;;
}
if(OpenSell())
{
Alert("INFO: sell order opened. ");
Phase = TRADE;
}
else
{
Alert("ERROR: sell order cannot be opened. ");
return;
}
}
}
if(Phase == TRADE)
{
if(tradeOpen && !PositionSelectByTicket(orderTicket))
{
tradeOpen = false;
if(!Initialization())
{
Alert("ERROR: expert refresh failed.");
ExpertRemove();
return;
}
}
}
}
Comments
Markdown Formatting Guide
# H1
## H2
### H3
**bold text**
*italicized text*
[title](https://www.example.com)

`code`
```
code block
```
> blockquote
- Item 1
- Item 2
1. First item
2. Second item
---