227 righe
7,6 KiB
MQL5
227 righe
7,6 KiB
MQL5
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Multitrade_w_Levels.mq5 |
|
||
|
|
//| Copyright 2018, MetaQuotes Software Corp. |
|
||
|
|
//| https://www.mql5.com |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
#property copyright "Copyright 2018, MetaQuotes Software Corp."
|
||
|
|
#property link "https://www.mql5.com"
|
||
|
|
#property version "1.00"
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Script program start function |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
|
||
|
|
#include <Trade\Trade.mqh>
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
input int max_band_size = 10;
|
||
|
|
input int number_of_levels = 2;
|
||
|
|
input double testing_volume = 0.1;
|
||
|
|
input double win_multiplier = 0.5;
|
||
|
|
input double lose_multiplier = 0.5;
|
||
|
|
input int box_height = 10;
|
||
|
|
input int box_length = 5;
|
||
|
|
|
||
|
|
|
||
|
|
#define BASE_MULT 0.5
|
||
|
|
#define POS_W_SHORT 1
|
||
|
|
#define POS_W_LONG 2
|
||
|
|
#define POS_W_BASE 0
|
||
|
|
|
||
|
|
struct Band
|
||
|
|
{
|
||
|
|
double top;
|
||
|
|
double bottom;
|
||
|
|
int number_levels;
|
||
|
|
int quanta; // @Init : round(max_band_size/ number of levels)
|
||
|
|
bool reset_limits;
|
||
|
|
double base_price;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct Box
|
||
|
|
{
|
||
|
|
double top;
|
||
|
|
double bottom;
|
||
|
|
int length;
|
||
|
|
bool first_box;
|
||
|
|
|
||
|
|
};
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Global Space |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
Band band;
|
||
|
|
Box box;
|
||
|
|
CTrade trader;
|
||
|
|
double Ask;
|
||
|
|
double Bid;
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void OnInit()
|
||
|
|
{
|
||
|
|
// init the Bands
|
||
|
|
band.top = max_band_size;
|
||
|
|
band.bottom = max_band_size;
|
||
|
|
band.number_levels = number_of_levels;
|
||
|
|
band.quanta = round(max_band_size/number_of_levels);
|
||
|
|
band.reset_limits = true;
|
||
|
|
|
||
|
|
box.first_box = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void OnTick()
|
||
|
|
{
|
||
|
|
//---
|
||
|
|
Ask = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits);
|
||
|
|
Bid = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits);
|
||
|
|
double price = NormalizeDouble((Ask + Bid) / 2, _Digits);
|
||
|
|
|
||
|
|
if(box.first_box)
|
||
|
|
{
|
||
|
|
update_box(price);
|
||
|
|
update_bands(price);
|
||
|
|
band.reset_limits = true;
|
||
|
|
box.first_box = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
if(Ask>box.top)
|
||
|
|
{
|
||
|
|
place_long(price, round(box_height*win_multiplier));
|
||
|
|
update_box(price, POS_W_LONG);
|
||
|
|
} // guide box goes long
|
||
|
|
else
|
||
|
|
if(Bid < box.bottom)
|
||
|
|
{
|
||
|
|
place_short(price,round(box_height*win_multiplier));
|
||
|
|
update_box(price, POS_W_SHORT);
|
||
|
|
} // guide box goes short
|
||
|
|
else
|
||
|
|
if(box.length<= 0)
|
||
|
|
{
|
||
|
|
update_box(price, POS_W_BASE);
|
||
|
|
} // box needs update
|
||
|
|
|
||
|
|
if(price>band.top || price < band.bottom)
|
||
|
|
{
|
||
|
|
close_all_open_trades();
|
||
|
|
} // price left the max_side (from either side)
|
||
|
|
else
|
||
|
|
if(band.reset_limits)
|
||
|
|
{
|
||
|
|
place_all_trade_levels(price);
|
||
|
|
} // all positions where closed (Set levels UP!)
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
box.length--;
|
||
|
|
Comment("Band: Top= "+band.top+" Bottom= "+band.bottom+" Quant= "+band.quanta+"\n"
|
||
|
|
+"Box: Top= "+box.top+" Bottom= "+box.bottom);
|
||
|
|
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void place_all_trade_levels(double price, double volume=0.1)
|
||
|
|
{
|
||
|
|
for(int i=0; i<band.number_levels; i++)
|
||
|
|
{
|
||
|
|
place_long(price+(band.quanta*i*_Point), band.quanta*(i+1), volume*i); // place the long
|
||
|
|
place_short(price-(band.quanta*i*_Point), band.quanta*(i+1), volume*i); // place the short
|
||
|
|
|
||
|
|
}
|
||
|
|
update_bands(price);
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void place_long(double price, int take_profit, double volume=0.1, bool not_stop=false)
|
||
|
|
{
|
||
|
|
if(not_stop)
|
||
|
|
{
|
||
|
|
trader.Sell(volume, NULL, price, 0, price-(take_profit*_Point), NULL);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
trader.SellStop(volume, price, NULL, 0, price-take_profit*_Point, ORDER_TIME_GTC, 0, NULL);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void place_short(double price, int take_profit, double volume=0.1, bool not_stop=false)
|
||
|
|
{
|
||
|
|
if(not_stop)
|
||
|
|
{
|
||
|
|
trader.Buy(volume, NULL, price, 0, price+(take_profit*_Point), NULL);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
trader.BuyStop(volume, price, NULL, 0, price+take_profit*_Point, ORDER_TIME_GTC, 0, NULL);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void close_all_open_trades()
|
||
|
|
{
|
||
|
|
for(int i=0; i<PositionsTotal(); i++)
|
||
|
|
{
|
||
|
|
ulong position_ticket = PositionGetTicket(i);
|
||
|
|
trader.PositionClose(position_ticket);
|
||
|
|
}
|
||
|
|
for(int j=0; j<OrdersTotal();j++){
|
||
|
|
ulong order_ticket = OrderGetTicket(j);
|
||
|
|
trader.OrderDelete(order_ticket);
|
||
|
|
|
||
|
|
}
|
||
|
|
band.reset_limits = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void update_bands(double price)
|
||
|
|
{
|
||
|
|
band.top = price + NormalizeDouble(max_band_size*_Point, _Digits);
|
||
|
|
band.bottom = price - NormalizeDouble(max_band_size*_Point, _Digits);
|
||
|
|
band.reset_limits = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void update_box(double price, int direction=POS_W_BASE)
|
||
|
|
{
|
||
|
|
if(direction == POS_W_SHORT)
|
||
|
|
{
|
||
|
|
box.top = price + (lose_multiplier*box_height*_Point);
|
||
|
|
box.bottom = price - (win_multiplier* box_height*_Point);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
if(direction == POS_W_LONG)
|
||
|
|
{
|
||
|
|
box.top = price + (win_multiplier*box_height*_Point);
|
||
|
|
box.bottom = price - (lose_multiplier* box_height*_Point);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
box.top = price + (BASE_MULT*box_height*_Point);
|
||
|
|
box.bottom = price - (BASE_MULT* box_height*_Point);
|
||
|
|
}
|
||
|
|
box.length = box_length;
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|