first push all - just my code

This commit is contained in:
Matt Corcoran
2024-10-25 12:08:52 +02:00
commit 890eaf31f5
10 changed files with 1840 additions and 0 deletions
+278
View File
@@ -0,0 +1,278 @@
#property library
#include <Trade/Trade.mqh>
#include <MyLibs/TimeZones.mqh>
#include <MyLibs/Myfunctions.mqh>
class CalculatePositionData : public CObject{
protected:
CTrade trade;
TimeZones tz;
CPositionInfo position;
MyFunctions mf;
bool check_lots(double &lots, string symbol);
bool normalise_price(double price, double &normalizedPrice, string symbol);
// double adjusted_point(string symbol);
public:
double calculate_stoploss(string symbol, double price, int order_side, string _sl_mode, double sl_var, ENUM_TIMEFRAMES atr_period);
double calculate_take_profit(string symbol, double price, double stoploss, int order_side, string mode_tp, double tp_var, ENUM_TIMEFRAMES atr_period);
double calculate_lots(string symbol, double sl_distance, double price, string mode_lot, double lot_var);
double calculate_trading_cost(string symbol, ulong position_ticket);
};
double CalculatePositionData::calculate_stoploss(string symbol, double price, int order_side, string mode_sl, double sl_var, ENUM_TIMEFRAMES atr_period){
// order_side int must be 1 for BUY or 2 for
double sl=0;
if(mode_sl=="NO_STOPLOSS"){
sl=0;
}
if(mode_sl=="SL_BREAKEVEN"){
// https://www.youtube.com/watch?v=idPulZ3_iR0
Alert("Not implemented yet yet");
}
if(mode_sl=="SL_FIXED_PIPS"){
// pips/poins = https://www.mql5.com/en/forum/187757
double adj_point = mf.adjusted_point(symbol);
if(order_side == 1){
sl = price - sl_var * adj_point;
if(!normalise_price(sl,sl,symbol)){return false;}
}
if(order_side == 2){
sl = price + sl_var * adj_point;
if(!normalise_price(sl,sl,symbol)){return false;}
}
}
if(mode_sl=="SL_FIXED_PERCENT"){
if(order_side == 1){
sl = (-1.0 * sl_var * price / 100.00) + price;
if(!normalise_price(sl,sl,symbol)){return false;}
}
if(order_side == 2){
sl = sl_var * price / 100.00 + price;
if(!normalise_price(sl,sl,symbol)){return false;}
}
}
if(mode_sl=="SL_ATR_MULTIPLE"){
int atr_handle = iATR(symbol,atr_period,14);
double atr[];
ArraySetAsSeries(atr,true);
CopyBuffer(atr_handle,MAIN_LINE,1,1,atr);
if(order_side == 1){
sl = price - (atr[0] * sl_var);
if(!normalise_price(sl,sl,symbol)){return false;}
}
if(order_side == 2){
sl = price + (atr[0] * sl_var);
if(!normalise_price(sl,sl,symbol)){return false;}
}
}
if(mode_sl=="SL_SPECIFIED_VALUE"){
double adj_point = mf.adjusted_point(symbol);
if(order_side == 1){
double pip_50_sl = price - 10 * adj_point;
if(sl_var >= pip_50_sl){
sl = pip_50_sl;
}
else sl = sl_var;
if(!normalise_price(sl,sl,symbol)){return false;}
}
if(order_side == 2){
double pip_50_sl = price + 10 * adj_point;
if(sl_var <= pip_50_sl){
sl = pip_50_sl;
}
else sl = sl_var;
sl = sl = sl_var;
if(!normalise_price(sl,sl,symbol)){return false;}
}
}
return sl;
}
double CalculatePositionData::calculate_take_profit(string symbol, double price, double stoploss, int order_side, string mode_tp, double _tp_var, ENUM_TIMEFRAMES atr_period){
// order_side int must be 1 for BUY or 2 for SELL
double tp=0;
if(mode_tp=="NO_TAKE_PROFIT"){
tp=0;
}
if(mode_tp=="TP_FIXED_PIPS"){
double adj_point = mf.adjusted_point(symbol);
if(order_side == 1){
tp = price + _tp_var * adj_point;
if(!normalise_price(tp,tp,symbol)){return false;}
}
if(order_side == 2){
tp = price - _tp_var * adj_point;
if(!normalise_price(tp,tp,symbol)){return false;}
}
}
if(mode_tp=="TP_FIXED_PERCENT"){
if(order_side == 1){
tp = _tp_var * price / 100.00 + price;
if(!normalise_price(tp,tp,symbol)){return false;}
}
if(order_side == 2){
tp = (-1 * _tp_var * price / 100.00) + price;
if(!normalise_price(tp,tp,symbol)){return false;}
}
}
if(mode_tp=="TP_ATR_MULTIPLE"){
int atr_handle = iATR(symbol,atr_period,14);
double atr[];
ArraySetAsSeries(atr,true);
CopyBuffer(atr_handle,MAIN_LINE,1,1,atr);
if(order_side == 1){
tp = price + (atr[0] * _tp_var);
if(!normalise_price(tp,tp,symbol)){return false;}
}
if(order_side == 2){
tp = price - (atr[0] * _tp_var);
if(!normalise_price(tp,tp,symbol)){return false;}
}
}
if(mode_tp=="TP_SL_MULTIPLE"){
if(order_side == 1){
double sl_size = price - stoploss;
tp = price + (_tp_var * sl_size);
if(!normalise_price(tp,tp,symbol)){return false;}
}
if(order_side == 2){
double sl_size = stoploss - price;
tp = price - (_tp_var * sl_size);
if(!normalise_price(tp,tp,symbol)){return false;}
}
}
if(mode_tp=="TP_SPECIFIED_VALUE"){
if(_tp_var!=0){
double adj_point = mf.adjusted_point(symbol);
if(order_side == 1){
double pip_limit = price + 10 * adj_point;
if(_tp_var <= pip_limit){
tp = pip_limit;
}
else tp = _tp_var;
if(!normalise_price(tp,tp,symbol)){return false;}
}
if(order_side == 2){
double pip_limit = price - 10 * adj_point;
if(_tp_var >= pip_limit){
tp = pip_limit;
}
else tp = _tp_var;
tp = tp = _tp_var;
if(!normalise_price(tp,tp,symbol)){return false;}
}
}
}
return tp;
}
double CalculatePositionData::calculate_lots(string symbol, double sl_distance, double price, string mode_lot, double lot_var){
double lots = 0;
double tick_size = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE);
double tick_value = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE);
double volume_step = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
double account_value = fmin(fmin(AccountInfoDouble(ACCOUNT_EQUITY),AccountInfoDouble(ACCOUNT_BALANCE)),AccountInfoDouble(ACCOUNT_MARGIN_FREE));
double risk_money = account_value * lot_var / 100;
if(mode_lot=="LOT_MODE_FIXED"){
lots = lot_var;
}
if(mode_lot=="LOT_MODE_PCT_RISK"){
double money_lot_step = (sl_distance / tick_size) * tick_value * volume_step;
lots = MathFloor(risk_money/money_lot_step) * volume_step;
}
if(mode_lot=="LOT_MODE_PCT_ACCOUNT"){
double money_lot_step = (price / tick_size) * tick_value * volume_step;
lots = MathFloor(risk_money/money_lot_step) * volume_step;
}
if(!check_lots(lots, symbol)){return false;}
return lots;
}
bool CalculatePositionData::check_lots(double &lots, string symbol){
double min = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
double max = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);
double step = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
if(lots<min){
Print("Lot size will be set to minimum allowed volume");
lots = min;
return true;
}
if(lots>max){
Print("Lot size greater than maximum allowed volume. lots:",lots,"max:",max);
return false;
}
lots = (int)MathFloor(lots/step) * step;
return true;
}
bool CalculatePositionData::normalise_price(double price, double &normalizedPrice, string symbol){
double tickSize;
if(!SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_SIZE,tickSize)){
Print("Failed to get tick size");
return false;
}
int symbol_digits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
normalizedPrice = NormalizeDouble(MathRound(price/tickSize)*tickSize, symbol_digits);
return true;
}
double CalculatePositionData::calculate_trading_cost(string symbol, ulong position_ticket){
position.SelectByTicket(position_ticket);
double swap = PositionGetDouble(POSITION_SWAP);
double commission = PositionGetDouble(POSITION_COMMISSION);
double tick_size = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE);
double tick_value = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE);
double lot_step = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
double lots = PositionGetDouble(POSITION_VOLUME);
double trading_cost = -1 * ((commission + swap) / tick_value * tick_size / lots);
return trading_cost;
}
+62
View File
@@ -0,0 +1,62 @@
#property library
#include <Trade/Trade.mqh>
enum CUSTOM_MAX_TYPE{
CM_WIN_LOSS_RATIO,
CM_WIN_PERCENT,
CM_WIN_PERCENT_200T
};
class CustomMax : public CObject{
protected:
double custom_criteria;
double CustomMax::win_loss_ratio();
double CustomMax::win_percent();
double CustomMax::win_percent_min_trades_200();
public:
double CustomMax::calculate_custom_criteria(CUSTOM_MAX_TYPE cm_type);
};
// CM_WIN_LOSS_RATIO,
// CM_WIN_PERCENT
double CustomMax::calculate_custom_criteria(CUSTOM_MAX_TYPE cm_type){
if(cm_type==CM_WIN_LOSS_RATIO){
custom_criteria = win_loss_ratio();
}
if(cm_type==CM_WIN_PERCENT){
custom_criteria = win_percent();
}
if(cm_type==CM_WIN_PERCENT_200T){
custom_criteria = win_percent_min_trades_200();
}
return custom_criteria;
}
double CustomMax::win_loss_ratio(){
double wins = TesterStatistics(STAT_PROFIT_TRADES);
double losses = TesterStatistics(STAT_LOSS_TRADES);
return wins/losses;
}
double CustomMax::win_percent(){
double wins = TesterStatistics(STAT_PROFIT_TRADES);
double total_trades = TesterStatistics(STAT_TRADES);
return wins / total_trades * 100;
}
double CustomMax::win_percent_min_trades_200(){
double wins = TesterStatistics(STAT_PROFIT_TRADES);
double total_trades = TesterStatistics(STAT_TRADES);
if(total_trades<200){
return 0;
}
else {
return wins / total_trades * 100;
}
}
Binary file not shown.
+205
View File
@@ -0,0 +1,205 @@
#property library
#include <Trade/Trade.mqh>
#include <MyLibs/MyFunctions.mqh>
class DrawdownControl : public CObject {
protected:
CTrade trade;
MyFunctions mf;
string data_file;
double daily_max_dd_per;
string daily_reset_time;
bool print_statments;
double acc_max_dd_per;
double equaty_control_high;
double equaty_control_low;
double daily_equity_start;
double daily_max_dd_target;
bool daily_dd_limit_reached;
bool write_global_var_data();
bool print_messages();
public:
void init_dd_control(string inp_data_file, double inp_acc_max_dd_per, double inp_daily_max_dd_per, string inp_daily_reset_time, bool inp_print_statments = true);
bool determine_daily_dd_limit();
double lot_correction_factor(double acc_equity_start, double min_lot_factor, double max_lot_factor, bool dynm_lot_factor=false, double dlf_trail_per=20);
double lot_correction_dynamic(double acc_dd_percent, double min_lot_factor, double max_lot_factor);
};
void DrawdownControl::init_dd_control(string inp_data_file, double inp_acc_max_dd_per, double inp_daily_max_dd_per, string inp_daily_reset_time, bool inp_print_statments = true) {
data_file = inp_data_file;
acc_max_dd_per = inp_acc_max_dd_per;
daily_max_dd_per = inp_daily_max_dd_per;
daily_reset_time = inp_daily_reset_time;
print_statments = inp_print_statments;
// If no data file exisits, create one and set global vairiables:
if(FileIsExist(data_file) == false) {
daily_equity_start = AccountInfoDouble(ACCOUNT_EQUITY);
daily_max_dd_target = daily_equity_start - (daily_equity_start * (daily_max_dd_per / 100));
daily_dd_limit_reached = false;
equaty_control_high = 9999999;
equaty_control_low = 0;
write_global_var_data();
}
// If file exisits read file:
if(FileIsExist(data_file) == true) {
int file_handle = FileOpen(data_file, FILE_READ | FILE_ANSI | FILE_TXT);
if(file_handle == INVALID_HANDLE) {
Print("Error opening file: ", data_file);
}
// If data file is older than 24h 10min create a new file and reset global vars:
long modifided_date = FileGetInteger(file_handle, FILE_MODIFY_DATE);
long time_delta = ((long)TimeCurrent() - modifided_date) / 60;
if(time_delta >= 1450) {
daily_equity_start = AccountInfoDouble(ACCOUNT_EQUITY);
daily_max_dd_target = daily_equity_start - (daily_equity_start * (daily_max_dd_per / 100));
daily_dd_limit_reached = false;
equaty_control_high = equaty_control_high;
equaty_control_low = equaty_control_low;
write_global_var_data();
Print(data_file, " is older than 24h and 10min; global vars reset!");
}
// If data file is younger than 24h+10 min read data and set global vars:
else {
daily_equity_start = (double)FileReadString(file_handle, 0);
daily_max_dd_target = (double)FileReadString(file_handle, 1);
daily_dd_limit_reached = FileReadBool(file_handle);
equaty_control_high = (double)FileReadString(file_handle, 3);
equaty_control_low = (double)FileReadString(file_handle, 4);;
}
FileClose(file_handle);
}
print_messages();
}
bool DrawdownControl::determine_daily_dd_limit() {
// Reset max equity at the start of each day:
string ct = TimeToString(TimeCurrent(), TIME_MINUTES);
if(ct == daily_reset_time) {
daily_equity_start = AccountInfoDouble(ACCOUNT_EQUITY);
daily_max_dd_target = (daily_equity_start - (daily_equity_start * (daily_max_dd_per / 100)));
daily_dd_limit_reached = false;
write_global_var_data();
print_messages();
}
// If in drawdown close all positions and delete orders
if(daily_dd_limit_reached || AccountInfoDouble(ACCOUNT_EQUITY) <= daily_max_dd_target) {
if(daily_dd_limit_reached == false) {
daily_dd_limit_reached = true;
write_global_var_data();
print_messages();
}
for(int i = PositionsTotal() - 1; i >= 0; i--) {
ulong ticket = PositionGetTicket(i);
trade.PositionClose(ticket);
}
for(int i = OrdersTotal() - 1; i >= 0; i--) {
ulong ticket = OrderGetTicket(i);
trade.OrderDelete(ticket);
}
}
return daily_dd_limit_reached;
}
// Reduces lot size as account apporchaes max allowed drawdown limit.
double DrawdownControl::lot_correction_factor(double acc_equity_start, double min_lot_factor, double max_lot_factor, bool dynm_lot_factor=false, double dlf_trail_per=20) {
double account_value = fmin(AccountInfoDouble(ACCOUNT_EQUITY), AccountInfoDouble(ACCOUNT_BALANCE));
double lot_factor;
// Interpolate to find lot factor between given min and max values.
if (account_value < acc_equity_start){
double acc_equity_min = acc_equity_start - (acc_equity_start * (acc_max_dd_per / 100));
double y1 = min_lot_factor;
double y2 = max_lot_factor;
double x1 = acc_equity_min;
double x = account_value;
double x2 = acc_equity_start;
lot_factor = y1 + (x - x1) * ((y2 - y1) / (x2 - x1));
}
else if(account_value >= acc_equity_start) {
if(dynm_lot_factor=true){
lot_factor = lot_correction_dynamic(dlf_trail_per, min_lot_factor, max_lot_factor);
}
else {
lot_factor = max_lot_factor;
}
}
return max_lot_factor;
}
double DrawdownControl::lot_correction_dynamic(double acc_dd_percent, double min_lot_factor, double max_lot_factor) {
double account_value = fmin(AccountInfoDouble(ACCOUNT_EQUITY), AccountInfoDouble(ACCOUNT_BALANCE));
double trail_point = account_value - (account_value * (acc_dd_percent / 100));
if(equaty_control_low < trail_point){
equaty_control_low = trail_point;
}
if(equaty_control_high < account_value){
equaty_control_high = account_value;
}
if(account_value < equaty_control_low){
equaty_control_low = account_value;
equaty_control_high = account_value + (account_value * (acc_dd_percent / 100));
}
// back-up to file every hour:
if(mf.is_new_bar(_Symbol, PERIOD_H1) == true){
write_global_var_data();
}
// Linear interpolation:
double y1 = min_lot_factor;
double y2 = max_lot_factor;
double x1 = equaty_control_low;
double x = account_value;
double x2 = equaty_control_high;
double y = y1 + (x - x1) * ((y2 - y1) / (x2 - x1));
return y;
}
bool DrawdownControl::write_global_var_data() {
int file_handle = FileOpen(data_file, FILE_WRITE | FILE_ANSI | FILE_TXT);
FileWrite(file_handle, daily_equity_start);
FileWrite(file_handle, daily_max_dd_target);
FileWrite(file_handle, daily_dd_limit_reached);
FileClose(file_handle);
Print(data_file, " written");
return true;
}
bool DrawdownControl::print_messages() {
if(print_statments == true) {
Print("TimeCurrent(): ", TimeToString(TimeCurrent()));
Print("Daily Equity Start: ", (int)daily_equity_start);
Print("Current Equity: ", (int)AccountInfoDouble(ACCOUNT_EQUITY));
Print("Daily Drawdown Limit: ", (int)daily_max_dd_target, " (", daily_max_dd_per, "%) of DES");
Print("Daily Drawdown Limit Hit: ", daily_dd_limit_reached);
}
return true;
}
+38
View File
@@ -0,0 +1,38 @@
#property library
enum LOT_MODE{
LOT_MODE_FIXED, // Fixed Lot Size
LOT_MODE_PCT_ACCOUNT, // Percent of Account (fixed)
LOT_MODE_PCT_RISK // Percent of Account at Risk (from SL)
};
enum SL_MODE{
SL_FIXED_PIPS, // Fixed Pips
SL_FIXED_PERCENT, // Fixed Percent
SL_ATR_MULTIPLE, // ATR Multiple
SL_SPECIFIED_VALUE, // Bespoke calculation in code
NO_STOPLOSS, // No Stop-loss
SL_BREAKEVEN, // Breakeven
};
enum TP_MODE{
TP_FIXED_PIPS, // Fixed Pips
TP_FIXED_PERCENT, // Fixed Percent
TP_ATR_MULTIPLE, // ATR Multiple
TP_SL_MULTIPLE, // Multiple of Risk (from sl)
TP_SPECIFIED_VALUE, // Bespoke calculation in code
NO_TAKE_PROFIT, // No Take-Profit
};
enum TIME_ZONES{
NY, // New York
Lon, // London
Ffm, // Frankfurt
Syd, // Sidney
Mosc, // Moscow
Tok, // Tokyo - no DST
};
enum MULTI_SYM_MODE{
MULTI_SYM_CHART, // Chart Symbol only
MULTI_SYM_FX_B5, // FX Benchmark 5
MULTI_SYM_FX_28 // FX 28 Majors
};
+171
View File
@@ -0,0 +1,171 @@
#property library
#include <Trade/Trade.mqh>
#include <MyLibs/TradingWindow.mqh>
class MyFunctions : public CObject{
protected:
CTrade trade;
TradingWindow tw;
datetime previousTime;
datetime bar_open_time;
public:
bool is_new_daily_bar(string symbol, datetime start_time);
double period_high(string symbol, int periods, int shift);
double period_low(string symbol, int periods, int shift);
void draw_line(double value, string name,color clr);
bool check_indicator_handles(int &indicator_handles[]);
double adjusted_point(string symbol);
double get_bid_ask_price(string symbol, int price_side);
bool is_new_bar(string symbol, ENUM_TIMEFRAMES time_frame);
bool trade_window(string t1, string t2, string time_zone, bool plot_range_inp=true);
};
bool MyFunctions::trade_window(string t1, string t2, string time_zone="Broker", bool plot_range_inp=true){
bool in_window = tw.define_window(t1, t2, time_zone, plot_range_inp);
return in_window;
}
//if(!mf.is_new_daily_bar(symbol, PERIOD_M1)){return;}
bool MyFunctions::is_new_bar(string symbol, ENUM_TIMEFRAMES time_frame){
bar_open_time = iTime(symbol,time_frame,0);
if(previousTime!=bar_open_time){
previousTime=bar_open_time;
return true;
}
return false;
}
// e.g. if(!mf.is_new_daily_bar(symbol, StringToTime("00:06"))){return;}
bool MyFunctions::is_new_daily_bar(string symbol, datetime start_time){
// https://www.youtube.com/watch?v=9BdnTcGrlUM (m-25:00)
bar_open_time = iTime(symbol,PERIOD_D1,0);
if(previousTime!=bar_open_time && TimeCurrent() > start_time){
previousTime=bar_open_time;
return true;
}
return false;
}
double MyFunctions::period_high(string symbol, int periods, int shift){
double highs[];
ArraySetAsSeries(highs,true);
CopyHigh(symbol,PERIOD_CURRENT,1,periods+1,highs);
double high = 0;
high=highs[shift];
for(int i=shift; i<shift+periods; i++){
if(high<highs[i]){
high=highs[i];
}
}
return(high);
}
double MyFunctions::period_low(string symbol, int periods, int shift){
double lows[];
ArraySetAsSeries(lows,true);
CopyLow(symbol,PERIOD_CURRENT,1,periods+1,lows);
double low = 0;
low=lows[shift];
for(int i=shift; i<shift+periods; i++){
if(low>lows[i]){
low=lows[i];
}
}
return(low);
}
void MyFunctions::draw_line(double value, string name,color clr){
// EG:
// ArrayResize(bar,1000);
// ArraySetAsSeries(bar, true);
// CopyRates(symbol,PERIOD_CURRENT,1,1000,bar);
// double close = bar[0].close;
// draw_line(close,"CLOSE",clrBlue);
if(ObjectFind(0,name)<0){
ResetLastError();
if(!ObjectCreate(0,name,OBJ_HLINE,0,0,value)){
Print(__FUNCTION__,": failed to create a horizontal line! Error code = ",GetLastError());
return;
}
ObjectSetInteger(0,name,OBJPROP_COLOR,clr);
ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_SOLID);
ObjectSetInteger(0,name,OBJPROP_WIDTH,1);
}
ResetLastError();
if(!ObjectMove(0,name,0,0,value)){
Print(__FUNCTION__,": failed to move the horizontal line! Error code = ",GetLastError());
return;
}
ChartRedraw();
}
bool MyFunctions::check_indicator_handles(int &indicator_handles[]){
// TODO check if working before implementaion:
// e.g. call via:
// int indicator_handles[] = {handle1, handle2, handle..};
// check_indicator_handles(indicator_handles);
for(int i =0; i < ArraySize(indicator_handles); i++){
if(indicator_handles[i] == INVALID_HANDLE){
Alert("Failed to create handle"); return false;
};
}
return true;
}
double MyFunctions::adjusted_point(string symbol){
int symbol_digits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
int digits_adjust=1;
if(symbol_digits==3 || symbol_digits==5){
digits_adjust=10;
}
double symbol_point_val = SymbolInfoDouble(symbol,SYMBOL_POINT);
double m_adjusted_point;
m_adjusted_point = symbol_point_val * digits_adjust;
return m_adjusted_point;
}
// price side - 1 for the ask price and 2 for the bid price
double MyFunctions::get_bid_ask_price(string symbol, int price_side){
int symbol_digits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
double symbol_point = SymbolInfoDouble(symbol, SYMBOL_POINT);
double ask = SymbolInfoDouble(symbol, SYMBOL_ASK);
ask = NormalizeDouble(ask, symbol_digits);
double bid = SymbolInfoDouble(symbol, SYMBOL_BID);
bid = NormalizeDouble(bid, symbol_digits);
double price = 0;
if(price_side==1){
price = ask;
}
else if(price_side==2){
price = bid;
}
return price;
}
+439
View File
@@ -0,0 +1,439 @@
#property library
#include <Trade/Trade.mqh>
#include <MyLibs/TimeZones.mqh>
#include <MyLibs/CalculatePositionData.mqh>
#include <Trade/PositionInfo.mqh>
#include <Trade/OrderInfo.mqh>
class OrderManagment : public CObject{
protected:
CTrade trade;
TimeZones tz;
CalculatePositionData cpd;
CPositionInfo m_position;
COrderInfo m_order;
double stop_loss;
double take_profit;
ulong posTicket;
int time_difference;
int total_open_buy_orders;
int total_open_sell_orders;
double current_price;
int total_pos;
long position_open_time;
long first_allowed_close_time;
datetime current_bar_open_time;
public:
bool open_buy_orders(string symbol, bool condition, ENUM_TIMEFRAMES atr_period, string _sl_mode, double sl_var, string _tp_mode, double tp_var, string _lot_mode, double lot_var,long magic_number);
bool open_sell_orders(string symbol, bool condition, ENUM_TIMEFRAMES atr_period, string _sl_mode, double sl_var, string _tp_mode, double tp_var, string _lot_mode, double lot_var,long magic_number);
bool open_buy_stop_order(string symbol, bool condition, double entry_price, datetime experation, ENUM_TIMEFRAMES atr_period, string _sl_mode, double sl_var, string _tp_mode, double tp_var, string _lot_mode, double lot_var,long magic_number);
bool open_sell_stop_order(string symbol, bool condition, double entry_price, datetime experation, ENUM_TIMEFRAMES atr_period, string _sl_mode, double sl_var, string _tp_mode, double tp_var, string _lot_mode, double lot_var,long magic_number);
bool close_buy_orders(string symbol, bool buy_out, int close_bars, ENUM_TIMEFRAMES close_bar_period, long magic_number);
bool close_sell_orders(string symbol, bool sell_out, int close_bars, ENUM_TIMEFRAMES close_bar_period, long magic_number);
bool first_profitable_close_exit(string symbol, ENUM_TIMEFRAMES close_bar_period, long magic_number);
bool daily_timed_exit(string symbol, datetime exit_time, int delay_days, long magic_number);
bool daily_timed_profit_exit(string symbol, ENUM_TIMEFRAMES close_bar_period, string exit_time, string tz, int delay_days, long magic_number);
int count_all_positions(string symbol, long magic_number);
int count_pending_orders(string symbol, ENUM_ORDER_TYPE pendingType, long magic);
double sl_specified_value_switch(string _sl_mode, double _inp_sl_var, double value);
double tp_specified_value_switch(string _tp_mode, double _inp_tp_var, double value);
int count_open_positions(string symbol,int order_side, long magic_number);
void break_even_stop(string symbol, ulong magic_number, int be_trigger_points, int be_puffer);
};
bool OrderManagment::open_buy_orders(string symbol, bool condition, ENUM_TIMEFRAMES atr_period, string _sl_mode, double sl_var, string _tp_mode, double tp_var, string _lot_mode, double lot_var, long magic_number){
if(condition == true){
current_price = SymbolInfoDouble(symbol, SYMBOL_ASK); // ask for buy side
total_open_buy_orders = count_open_positions(symbol, 1, magic_number);
if(total_open_buy_orders == 0){
stop_loss = cpd.calculate_stoploss(symbol, current_price, 1, _sl_mode, sl_var, atr_period);
take_profit = cpd.calculate_take_profit(symbol, current_price, stop_loss, 1, _tp_mode, tp_var, atr_period);
double sl_distance = current_price-stop_loss;
double lots = cpd.calculate_lots(symbol, sl_distance, current_price, _lot_mode, lot_var);
trade.SetExpertMagicNumber(magic_number);
string comment = "Magic Number: " + IntegerToString(magic_number);
trade.PositionOpen(symbol,ORDER_TYPE_BUY,lots,current_price,stop_loss,take_profit,comment);
}
}
return true;
}
bool OrderManagment::open_sell_orders(string symbol, bool condition, ENUM_TIMEFRAMES atr_period, string _sl_mode, double sl_var, string _tp_mode, double tp_var, string _lot_mode, double lot_var,long magic_number){
if(condition == true){
// if(!SymbolInfoTick(symbol,currentTick)){Print("FAILED TO GET TICK:", symbol);return false;}
current_price = SymbolInfoDouble(symbol, SYMBOL_BID); // bid for sell side
total_open_sell_orders = count_open_positions(symbol, 2, magic_number);
if(total_open_sell_orders == 0){
stop_loss = cpd.calculate_stoploss(symbol, current_price, 2, _sl_mode, sl_var, atr_period);
take_profit = cpd.calculate_take_profit(symbol, current_price, stop_loss, 2, _tp_mode, tp_var, atr_period);
double sl_distance = stop_loss-current_price;
double lots = cpd.calculate_lots(symbol, sl_distance, current_price, _lot_mode, lot_var);
trade.SetExpertMagicNumber(magic_number);
string comment = "Magic Number: " + IntegerToString(magic_number);
trade.PositionOpen(symbol,ORDER_TYPE_SELL,lots,current_price,stop_loss,take_profit,comment);
}
}
return true;
}
// some usfull comment here
bool OrderManagment::open_buy_stop_order(string symbol, bool condition, double entry_price, datetime experation, ENUM_TIMEFRAMES atr_period, string _sl_mode, double sl_var,string _tp_mode, double tp_var, string _lot_mode, double lot_var,long magic_number){
if(condition == true){
total_open_buy_orders = count_open_positions(symbol, 1, magic_number);
if(total_open_buy_orders == 0){
stop_loss = cpd.calculate_stoploss(symbol, entry_price, 1, _sl_mode, sl_var, atr_period);
take_profit = cpd.calculate_take_profit(symbol, entry_price, stop_loss, 1, _tp_mode, tp_var, atr_period);
double sl_distance = entry_price-stop_loss;
double lots = cpd.calculate_lots(symbol, sl_distance, entry_price, _lot_mode, lot_var);
trade.SetExpertMagicNumber(magic_number);
string comment = "Magic Number: " + IntegerToString(magic_number);
trade.BuyStop(lots, entry_price, symbol, stop_loss, take_profit, ORDER_TIME_SPECIFIED, experation, comment);
}
}
return true;
}
bool OrderManagment::open_sell_stop_order(string symbol, bool condition, double entry_price, datetime experation, ENUM_TIMEFRAMES atr_period, string _sl_mode, double sl_var, string _tp_mode, double tp_var, string _lot_mode, double lot_var,long magic_number){
if(condition == true){
total_open_sell_orders = count_open_positions(symbol, 2, magic_number);
if(total_open_sell_orders == 0){
stop_loss = cpd.calculate_stoploss(symbol, entry_price, 2, _sl_mode, sl_var, atr_period);
take_profit = cpd.calculate_take_profit(symbol, entry_price, stop_loss, 2, _tp_mode, tp_var, atr_period);
double sl_distance = stop_loss-entry_price;
double lots = cpd.calculate_lots(symbol, sl_distance, entry_price, _lot_mode, lot_var);
trade.SetExpertMagicNumber(magic_number);
string comment = "Magic Number: " + IntegerToString(magic_number);
trade.SellStop(lots, entry_price, symbol, stop_loss, take_profit, ORDER_TIME_SPECIFIED, experation, comment);
}
}
return true;
}
bool OrderManagment::close_buy_orders(string symbol, bool condition, int close_bars, ENUM_TIMEFRAMES close_bar_period, long magic_number){
for(int i = PositionsTotal()-1; i >=0; i--){
posTicket = PositionGetTicket(i);
if(PositionGetString(POSITION_SYMBOL) == symbol && PositionGetInteger(POSITION_MAGIC) == magic_number){
time_difference = Bars(symbol, close_bar_period, PositionGetInteger(POSITION_TIME), TimeCurrent()) - 1;
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY){
if(condition){
trade.PositionClose(posTicket);
}
if(close_bars > 0){
if(time_difference >= close_bars){
trade.PositionClose(posTicket);
}
}
}
}
}
return true;
}
bool OrderManagment::close_sell_orders(string symbol, bool condition, int close_bars, ENUM_TIMEFRAMES close_bar_period, long magic_number){
for(int i = PositionsTotal()-1; i >=0; i--){
posTicket = PositionGetTicket(i);
if(PositionGetString(POSITION_SYMBOL) == symbol && PositionGetInteger(POSITION_MAGIC) == magic_number){
time_difference = Bars(symbol, close_bar_period, PositionGetInteger(POSITION_TIME), TimeCurrent()) - 1;
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL){
if(condition){trade.PositionClose(posTicket);}
if(close_bars > 0){
if(time_difference >= close_bars){
trade.PositionClose(posTicket);
}
}
}
}
}
return true;
}
// order_side int must be 1 for BUY or 2 for SELL
int OrderManagment::count_open_positions(string symbol,int order_side, long magic_number){
int count = 0;
bool match = (PositionGetInteger(POSITION_MAGIC)==magic_number);
for(int i = PositionsTotal()-1; i >=0; i--){
ulong ticket = PositionGetTicket(i);
if(PositionGetString(POSITION_SYMBOL) == symbol && PositionGetInteger(POSITION_MAGIC)==magic_number){
// Count only Buy orders:
if(order_side == 1){
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY){
count = count + 1;
}
}
// Count only Sell orders:
if(order_side == 2){
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL){
count = count + 1;
}
}
}
}
return count;
}
int OrderManagment::count_all_positions(string symbol, long magic_number){
int count = 0;
for(int i = PositionsTotal()-1; i >=0; i--){
ulong ticket = PositionGetTicket(i);
if(PositionGetString(POSITION_SYMBOL) == symbol && PositionGetInteger(POSITION_MAGIC)==magic_number){
count = count + 1;
}
}
return count;
}
bool OrderManagment::daily_timed_exit(string symbol, datetime exit_time, int delay_days, long magic_number){
for(int i = PositionsTotal()-1; i >=0; i--){
posTicket = PositionGetTicket(i);
position_open_time = PositionGetInteger(POSITION_TIME);
if((int)position_open_time>0){
first_allowed_close_time = position_open_time + (delay_days * PeriodSeconds(PERIOD_D1));
if(TimeCurrent() > first_allowed_close_time){
// datetime broker_close_time = tz.timezone_conversions(cw_tzone, StringToTime(exit_time), "Broker");
if(TimeCurrent()>= exit_time){
if(PositionGetString(POSITION_SYMBOL) == symbol && PositionGetInteger(POSITION_MAGIC) == magic_number){
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY){
trade.PositionClose(posTicket);
}
// Sell orders:
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL){
trade.PositionClose(posTicket);
}
}
}
}
}
}
return true;
}
bool OrderManagment::daily_timed_profit_exit(string symbol, ENUM_TIMEFRAMES close_bar_period, string exit_time, string cw_tzone, int delay_days, long magic_number){
// om.daily_timed_profit_exit(_Symbol, PERIOD_CURRENT, "16:45", "17:00", "NY", 1, inp_magic);
for(int i = PositionsTotal()-1; i >=0; i--){
posTicket = PositionGetTicket(i);
position_open_time = PositionGetInteger(POSITION_TIME);
if((int)position_open_time>0){
first_allowed_close_time = position_open_time + (delay_days * PeriodSeconds(PERIOD_D1));
if(TimeCurrent() > first_allowed_close_time){
datetime broker_close_time = tz.timezone_conversions(cw_tzone, StringToTime(exit_time), "Broker");
if(TimeCurrent()>= broker_close_time){
if(PositionGetString(POSITION_SYMBOL) == symbol && PositionGetInteger(POSITION_MAGIC) == magic_number){
double position_open_price = PositionGetDouble(POSITION_PRICE_OPEN);
double spread = SymbolInfoDouble(symbol,SYMBOL_ASK) - SymbolInfoDouble(symbol,SYMBOL_BID);
double bar_close = iClose(_Symbol, close_bar_period, 1); // shift 1 because 0 = live candle.
double trading_cost = cpd.calculate_trading_cost(symbol, posTicket);
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY){
if(bar_close > (position_open_price + spread + trading_cost)){
trade.PositionClose(posTicket);
}
}
// Sell orders:
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL){
if(bar_close < position_open_price - spread - trading_cost){
trade.PositionClose(posTicket);
}
}
}
}
}
}
}
return true;
}
bool OrderManagment::first_profitable_close_exit(string symbol, ENUM_TIMEFRAMES close_bar_period, long magic_number){
// om.first_profitable_close_exit(_Symbol, PERIOD_CURRENT, inp_magic);
position_open_time = PositionGetInteger(POSITION_TIME);
first_allowed_close_time = position_open_time + PeriodSeconds(close_bar_period);
if((int)position_open_time>0){
if(TimeCurrent() > first_allowed_close_time){
for(int i = PositionsTotal()-1; i >=0; i--){
posTicket = PositionGetTicket(i);
if(PositionGetString(POSITION_SYMBOL) == symbol && PositionGetInteger(POSITION_MAGIC) == magic_number){
double position_open_price = PositionGetDouble(POSITION_PRICE_OPEN);
double spread = SymbolInfoDouble(symbol,SYMBOL_ASK) - SymbolInfoDouble(symbol,SYMBOL_BID);
double bar_close = iClose(_Symbol,close_bar_period, 1); // shift 1 because 0 = live candle.
double trading_cost = cpd.calculate_trading_cost(symbol, posTicket);
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY){
if(bar_close > (position_open_price + spread + trading_cost)){
trade.PositionClose(posTicket);
}
}
// Sell orders:
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL){
if(bar_close < position_open_price - spread - trading_cost){
trade.PositionClose(posTicket);
}
}
}
}
}
}
return true;
}
// e.g. int buy_stop_count = om.count_pending_orders(symbol, ORDER_TYPE_BUY_STOP, inp_magic);
// order types: ORDER_TYPE_BUY_LIMIT, ORDER_TYPE_SELL_LIMIT, ORDER_TYPE_BUY_STOP, ORDER_TYPE_SELL_STOP
int OrderManagment::count_pending_orders(string symbol, ENUM_ORDER_TYPE order_type, long magic){
int count = 0;
for(int i=OrdersTotal()-1;i>=0;i--) {
if(m_order.SelectByIndex(i)){
if( OrderGetInteger(ORDER_MAGIC) == magic && OrderGetString(ORDER_SYMBOL) == symbol){
if(m_order.OrderType()==order_type){
count++;
}
}
}
}
return(count);
}
void OrderManagment::break_even_stop(string symbol, ulong magic_number, int be_trigger_points, int be_puffer){
if(PositionGetString(POSITION_SYMBOL) == symbol && PositionGetInteger(POSITION_MAGIC) == magic_number){
int symbol_digits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
double symbol_point = SymbolInfoDouble(symbol, SYMBOL_POINT);
double ask = SymbolInfoDouble(symbol, SYMBOL_ASK);
ask = NormalizeDouble(ask, symbol_digits);
double bid = SymbolInfoDouble(symbol, SYMBOL_BID);
bid = NormalizeDouble(bid, symbol_digits);
if(be_trigger_points !=0){
for(int i = PositionsTotal()-1; i >=0; i--){
ulong ticket = PositionGetTicket(i);
if(PositionSelectByTicket(ticket)){
double position_open_price = PositionGetDouble(POSITION_PRICE_OPEN);
double position_volume = PositionGetDouble(POSITION_VOLUME);
double position_sl = PositionGetDouble(POSITION_SL);
double position_tp = PositionGetDouble(POSITION_TP);
ENUM_POSITION_TYPE position_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
if(position_type == POSITION_TYPE_BUY){
if(bid > position_open_price + be_trigger_points * symbol_point){
double sl = position_open_price + be_puffer * symbol_point;
sl = NormalizeDouble(sl, symbol_digits);
if(sl > position_sl){
if(trade.PositionModify(ticket, sl, position_tp)){
Print("-----------------------------------Stop moved to break even");
}
}
}
}
else if(position_type == POSITION_TYPE_SELL){
if(ask < position_open_price - be_trigger_points * symbol_point){
double sl = position_open_price - be_puffer * symbol_point;
sl = NormalizeDouble(sl, symbol_digits);
if(sl < position_sl){
if(trade.PositionModify(ticket, sl, position_tp)){
Print("-----------------------------------Stop moved to break even");
}
}
}
}
}
}
}
}
}
double OrderManagment::sl_specified_value_switch(string _sl_mode, double _inp_sl_var, double value){
double sl = 0;
if(_sl_mode=="SL_SPECIFIED_VALUE"){sl = value;}
if(_sl_mode!="SL_SPECIFIED_VALUE"){sl = _inp_sl_var;}
return sl;
}
double OrderManagment::tp_specified_value_switch(string _tp_mode, double _inp_tp_var, double value){
double tp = 0;
if(_tp_mode=="SL_SPECIFIED_VALUE"){tp = value;}
if(_tp_mode!="SL_SPECIFIED_VALUE"){tp = _inp_tp_var;}
return tp;
}
+414
View File
@@ -0,0 +1,414 @@
#property library
#include <Trade/Trade.mqh>
#include <MyLibs/TimeZones.mqh>
class RangeCalculator : public CObject{
protected:
TimeZones tz;
bool days_initlised;
bool range_initlised;
string symbol;
ENUM_TIMEFRAMES calc_period;
string inp_r_start_string;
int r_duration;
int r_expire;
int r_close;
string inp_timezone;
bool sun;
bool mon;
bool tue;
bool wed;
bool thu;
bool fri;
bool sat;
bool plot_range;
datetime start_time; // Start of the range
datetime end_time; // end of the range
datetime order_expire_time; // end of the range
datetime close_time; // Close time
double high; // high of the range
double low; // low of the range
double mid; // mid of the range
bool f_entry; // flag if we are inside of the range
bool f_high_breakout; // flag if a high breakout occurred
bool f_low_breakout; // flag if a low breakout occurred
bool above_last;
bool above_current;
bool below_last;
bool below_current;
// private functions
void update_objects();
void draw_objects();
void define_new_range();
bool convert_input_time_strings(string t1, string t2, string t3, string t4);
public:
void calculate_range();
double get_range_high();
double get_range_low();
double get_range_mid();
datetime get_range_start();
datetime get_range_end();
datetime get_order_expire_time();
datetime get_range_close();
bool get_range_high_breakout();
bool get_range_low_breakout();
bool initilise_range(string inp_symbol, ENUM_TIMEFRAMES _calc_period, string t0, string t1, string t2, string t3, string time_zone, bool plot_range_inp);
void range_days(bool _inp_sun, bool _inp_mon, bool _inp_tue, bool _inp_wed, bool _inp_thu, bool _inp_fri, bool _inp_sat);
};
void RangeCalculator::range_days(bool _inp_sun, bool _inp_mon, bool _inp_tue, bool _inp_wed, bool _inp_thu, bool _inp_fri, bool _inp_sat){
sun = _inp_sun;
mon = _inp_mon;
tue = _inp_tue;
wed = _inp_wed;
thu = _inp_thu;
fri = _inp_fri;
sat = _inp_sat;
days_initlised = true;
}
bool RangeCalculator::initilise_range(string inp_symbol, ENUM_TIMEFRAMES _calc_period, string t1, string t2, string t3, string t4, string time_zone, bool plot_range_inp){
inp_r_start_string = t1;
inp_timezone = time_zone;
symbol = inp_symbol;
calc_period =_calc_period;
plot_range = plot_range_inp;
start_time = 0;
end_time = 0;
close_time = 0;
high = 0;
low = DBL_MAX;
mid = 0;
f_entry = false;
f_high_breakout = false;
f_low_breakout = false;
above_last = false;
above_current= false;
below_last= false;
below_current= false;
if(!days_initlised){
sun = true;
mon = true;
tue = true;
wed = true;
thu = true;
fri = true;
sat = true;
}
range_initlised = true;
bool corret_inputs = convert_input_time_strings(t1, t2, t3, t4);
if(corret_inputs = false){
return false;
}
return true;
}
bool RangeCalculator::convert_input_time_strings(string t1, string t2, string t3, string t4){
datetime _t1 = StringToTime(t1);
datetime _t2 = StringToTime(t2);
datetime _t3 = StringToTime(t3);
datetime _t4 = StringToTime(t4);
if(_t1 > _t2){
_t2 = _t2 + PeriodSeconds(PERIOD_D1);
_t3 = _t3 + PeriodSeconds(PERIOD_D1);
_t4 = _t4 + PeriodSeconds(PERIOD_D1);
}
if(_t2 > _t3){
_t3 = _t3 + PeriodSeconds(PERIOD_D1);
_t4 = _t4 + PeriodSeconds(PERIOD_D1);
}
if(_t3 > _t4){
_t4 = _t4 + PeriodSeconds(PERIOD_D1);
}
r_duration = (int)(_t2 - _t1);
r_expire = (int)(_t3 - _t1);
r_close = (int)(_t4 - _t1);
if(_t4 - _t1 >= PeriodSeconds(PERIOD_D1)){
Alert("INCORRECT RANGE INPUTS!");
return false;
}
return true;
}
// high of the range
double RangeCalculator::get_range_high(){
return high;
};
// low of the range
double RangeCalculator::get_range_low(){
return low;
};
// mid of the range
double RangeCalculator::get_range_mid(){
return mid;
};
datetime RangeCalculator::get_range_start(){
return start_time;
};
datetime RangeCalculator::get_range_end(){
return end_time;
};
datetime RangeCalculator::get_order_expire_time(){
return order_expire_time;
};
datetime RangeCalculator::get_range_close(){
return close_time;
};
// flag if a high breakout occurred
bool RangeCalculator::get_range_high_breakout(){
return f_high_breakout;
};
// flag if a low breakout occurred
bool RangeCalculator::get_range_low_breakout(){
return f_low_breakout;
};
void RangeCalculator::calculate_range(){
f_high_breakout = false;
f_low_breakout = false;
double last_bar_high = iHigh(symbol, calc_period, 1); // shift 1 because 0 = live candle:
double last_bar_low = iLow(symbol, calc_period, 1); // shift 1 because 0 = live candle:
// range calculation
if(TimeCurrent() >= start_time && TimeCurrent() <= end_time){
// set flag
f_entry = true;
// new high
if(last_bar_high > high){
high = last_bar_high;
mid = (high + low)/2;
if(plot_range){
update_objects();
}
}
// new low
if(last_bar_low < low){
low = last_bar_low;
mid = (high + low)/2;
if(plot_range){
update_objects();
}
}
}
// calculate new reange if
if( (TimeCurrent() >= close_time) // close time reached
|| (end_time == 0) // range not calculated yet
|| (end_time !=0 && TimeCurrent() > end_time && !f_entry) // there was a range calculated but no tick inside.
){
define_new_range();
}
// check if we are after the range end
if(TimeCurrent() >= end_time && end_time > 0 && f_entry){
if(!f_high_breakout && last_bar_high >= high){
above_last = above_current;
above_current= true;
if(above_last==false && above_current == true){
f_high_breakout = true;
}
else(f_high_breakout = false);
}
if(!f_low_breakout && last_bar_low >= low){
below_last = below_current;
below_current = true;
if(below_last == false && below_current == true){
f_low_breakout = true;
}
else(f_low_breakout = false);
}
}
}
void RangeCalculator::define_new_range(){
// reset range vars
start_time = 0;
end_time = 0;
order_expire_time = 0;
close_time = 0;
high = 0;
low = INT_MAX;
mid = 0;
f_entry = false;
// calculate range start time:
datetime r_st = StringToTime(inp_r_start_string);
start_time = tz.timezone_conversions(inp_timezone, r_st, "Broker");
for(int i=0; i<8; i++){
MqlDateTime tmp;
TimeToStruct(start_time,tmp);
int dow = tmp.day_of_week;
if(TimeCurrent()>=start_time
|| (dow==0 && !sun)
|| (dow==1 && !mon)
|| (dow==2 && !tue)
|| (dow==3 && !wed)
|| (dow==4 && !thu)
|| (dow==5 && !fri)
|| (dow==6 && !sat)
){
start_time += PeriodSeconds(PERIOD_D1);
}
}
end_time = start_time + r_duration;
order_expire_time = start_time + r_expire;
close_time = start_time + r_close;
if(plot_range){
draw_objects();
}
}
void RangeCalculator::update_objects(){
string name = "Range Mid " + (string)start_time;
ObjectSetDouble(NULL, name, OBJPROP_PRICE,0, mid);
ObjectSetDouble(NULL, name, OBJPROP_PRICE,1, mid);
// ObjectSetString(NULL, name , OBJPROP_TOOLTIP, "Range Mid");
name = "Order expire " + (string)order_expire_time;
ObjectSetDouble(NULL, name, OBJPROP_PRICE,0, high);
ObjectSetDouble(NULL, name, OBJPROP_PRICE,1, low);
name = "Range start " + (string)start_time;
ObjectSetDouble(NULL, name, OBJPROP_PRICE,0, high);
ObjectSetDouble(NULL, name, OBJPROP_PRICE,1, low);
name = "Range end " + (string)end_time;
ObjectSetDouble(NULL, name, OBJPROP_PRICE,0, high);
ObjectSetDouble(NULL, name, OBJPROP_PRICE,1, low);
datetime rct = r_close>=0 ? close_time : INT_MAX;
name = "Range close " + (string)rct;
ObjectSetDouble(NULL, name, OBJPROP_PRICE,0, high);
ObjectSetDouble(NULL, name, OBJPROP_PRICE,1, low);
name = "Range High " + (string)rct;
ObjectSetDouble(NULL, name, OBJPROP_PRICE,0, high);
ObjectSetDouble(NULL, name, OBJPROP_PRICE,1, high);
name = "Range Low " + (string)rct;
ObjectSetDouble(NULL, name, OBJPROP_PRICE,0, low);
ObjectSetDouble(NULL, name, OBJPROP_PRICE,1, low);
name = "range box "+ (string)start_time;
ObjectSetDouble(NULL, name, OBJPROP_PRICE,0, high);
ObjectSetDouble(NULL, name, OBJPROP_PRICE,1, low);
ObjectSetDouble(NULL, name +" ", OBJPROP_PRICE,0, high);
ObjectSetDouble(NULL, name +" ", OBJPROP_PRICE,1, low);
}
void RangeCalculator::draw_objects(){
datetime rct = r_close>=0 ? close_time : INT_MAX;
// Range mid line
string name = "Range Mid " + (string)start_time;;
ObjectCreate(NULL, name, OBJ_TREND, 0, start_time, mid, rct, mid);
ObjectSetString(NULL, name , OBJPROP_TOOLTIP, "Range Mid" + (string)mid);
ObjectSetInteger(NULL, name, OBJPROP_COLOR, clrGray);
ObjectSetInteger(NULL, name, OBJPROP_WIDTH, 1);
ObjectSetInteger(NULL, name, OBJPROP_STYLE, STYLE_DOT);
// order lines
string name2 = "Order expire " + (string)order_expire_time;
ObjectCreate(NULL, name2, OBJ_TREND, 0, order_expire_time, low, order_expire_time, high);
ObjectSetString(NULL, name2, OBJPROP_TOOLTIP, "start of the range \n" + TimeToString(order_expire_time,TIME_DATE|TIME_MINUTES));
ObjectSetInteger(NULL, name2, OBJPROP_COLOR, C'139,41,41');
ObjectSetInteger(NULL, name2 ,OBJPROP_WIDTH, 2);
ObjectSetInteger(NULL, name2,OBJPROP_BACK, true);
name2 = "Range start " + (string)start_time;
ObjectCreate(NULL, name2, OBJ_TREND, 0, start_time, low, start_time, high);
ObjectSetInteger(NULL, name2, OBJPROP_COLOR, clrBlack);
ObjectSetInteger(NULL, name2 ,OBJPROP_WIDTH, 2);
ObjectSetInteger(NULL, name2,OBJPROP_BACK, true);
name2 = "Range end " + (string)end_time;
ObjectCreate(NULL, name2, OBJ_TREND, 0, end_time, low, end_time, high);
ObjectSetInteger(NULL, name2, OBJPROP_COLOR, clrBlack);
ObjectSetInteger(NULL, name2 ,OBJPROP_WIDTH, 2);
ObjectSetInteger(NULL, name2,OBJPROP_BACK, true);
name2 = "Range close " + (string)rct;
ObjectCreate(NULL, name2, OBJ_TREND, 0, rct, low, rct, high);
ObjectSetInteger(NULL, name2, OBJPROP_COLOR, clrBlack);
ObjectSetInteger(NULL, name2 ,OBJPROP_WIDTH, 2);
ObjectSetInteger(NULL, name2,OBJPROP_BACK, true);
name2 = "Range High " + (string)rct;
ObjectCreate(NULL, name2, OBJ_TREND, 0, start_time, high, rct, high);
ObjectSetInteger(NULL, name2, OBJPROP_COLOR, clrBlack);
ObjectSetInteger(NULL, name2 ,OBJPROP_WIDTH, 2);
ObjectSetInteger(NULL, name2,OBJPROP_BACK, true);
name2 = "Range Low " + (string)rct;
ObjectCreate(NULL, name2, OBJ_TREND, 0, start_time, low, rct, low);
ObjectSetInteger(NULL, name2, OBJPROP_COLOR, clrBlack);
ObjectSetInteger(NULL, name2 ,OBJPROP_WIDTH, 2);
ObjectSetInteger(NULL, name2 ,OBJPROP_BACK, true);
// Box
name = "range box " + (string)start_time;
ObjectCreate(NULL, name, OBJ_RECTANGLE, 0, start_time, high, end_time, low);
ObjectSetString(NULL,name,OBJPROP_TOOLTIP,"\n");
ObjectSetInteger(NULL, name,OBJPROP_COLOR, C'128,177,173');
ObjectSetInteger(NULL, name,OBJPROP_FILL, true);
ObjectSetInteger(NULL, name,OBJPROP_BACK, true);
ObjectCreate(NULL, name + " ", OBJ_RECTANGLE, 0, end_time, high, rct, low);
ObjectSetString(NULL, name+ " ", OBJPROP_TOOLTIP, "\n");
ObjectSetInteger(NULL, name + " ",OBJPROP_FILL, true);
ObjectSetInteger(NULL, name + " ",OBJPROP_COLOR, C'165,220,215' );
ObjectSetInteger(NULL, name + " ",OBJPROP_BACK, true);
ChartRedraw();
}
+168
View File
@@ -0,0 +1,168 @@
#property library
#include <Trade/Trade.mqh>
#include <MyLibs/DealingWithTime.mqh>
class TimeZones: public CObject{
protected:
string dt_s;
int len;
string dt_string;
datetime tC, tGMT, tNY, tLon, tFfm, tMosc, tSyd, tTok;
datetime tz_time;
string tz_date;
datetime time_start;
datetime time_end;
bool is_time;
datetime tGIVEN;
datetime tREQ;
datetime tzt;
datetime tz_req;
double ny_daily_close_protected(string symbol, int shift_days, bool print_data=false);
double required_close;
public:
string get_date_string_from_datetime(datetime dt);
datetime get_timezone_time(string time_zone, bool print_time);
datetime timezone_conversions(string time_zone_known, datetime time_given, string time_zone_required);
double ny_daily_close(string symbol, int shift_days, bool print_data=false);
};
string TimeZones::get_date_string_from_datetime(datetime dt){
dt_s = TimeToString(dt);
len = StringLen(dt_s);
dt_string = StringSubstr(dt_s, 0, len-5);
return dt_string;
}
// bool TimeZones::trading_window(string time_zone, string start_time, string end_time){
// // https://www.youtube.com/watch?v=V_qh7sTbl80
// // e.g:
// // bool trade_window = trading_window(x,x,x);
// // bool long_in = trade_window
// // && close < ma[0];
// tz_time = get_timezone_time(time_zone, false);
// Print(tz_time);
// // Get the current date for the required time zone:
// tz_date = get_date_string_from_datetime(tz_time);
// // Define the start and end times on correct date:
// time_start = StringToTime(tz_date + start_time);
// time_end = StringToTime(tz_date + end_time);
// if(time_start>time_end){
// time_start = time_start - PeriodSeconds(PERIOD_D1);
// }
// is_time = tz_time >= time_start && tz_time < time_end;
// return is_time;
// }
datetime TimeZones::get_timezone_time(string time_zone, bool print_time){
// https://www.mql5.com/en/code/45287
// https://www.mql5.com/en/articles/9926
// https://www.mql5.com/en/articles/9929
checkTimeOffset(TimeCurrent()); // check changes of DST
// cto();
tC = TimeCurrent();
tGMT = TimeCurrent() + OffsetBroker.actOffset; // GMT
tNY = tGMT - (NYShift+DST_USD); // time in New York (EST)
tLon = tGMT - (LondonShift+DST_EUR); // time in London
tFfm = tGMT - (FfmShift+DST_EUR); // time in Frankfurt
tSyd = tGMT - (SidneyShift+DST_AUD); // time in Sidney
tMosc = tGMT - (MoskwaShift+DST_RUS); // time in Moscow
tTok = tGMT - (TokyoShift); // time in Tokyo - no DST
if(print_time==true){
Print("----------------------------------");
Print("Broker: ", tC);
Print("GMT: ", tGMT);
Print("time in New York: ", tNY);
Print("time in London: ", tLon);
Print("time in Frankfurt: ", tFfm);
Print("time in Sidney: ", tSyd);
Print("time in Moscow: ", tMosc);
Print("time in Tokyo: ", tTok);
}
if(time_zone=="NY"){return tNY;}
if(time_zone=="Lon"){return tLon;}
if(time_zone=="Ffm"){return tFfm;}
if(time_zone=="Syd"){return tSyd;}
if(time_zone=="Mosc"){return tMosc;}
if(time_zone=="Tok"){return tTok;}
return NULL;
}
datetime TimeZones::timezone_conversions(string time_zone_known, datetime time_given, string time_zone_required){
// https://www.mql5.com/en/code/45287
// https://www.mql5.com/en/articles/9926
// https://www.mql5.com/en/articles/9929
tGIVEN = time_given; //StringToTime(time_given);
checkTimeOffset(tGIVEN); // check changes of DST
// Get GMT:
if(time_zone_known=="GMT" ){tGMT = tGIVEN;}
if(time_zone_known=="Broker" ){tGMT = tGIVEN + OffsetBroker.actOffset;}
if(time_zone_known=="NY" ){tGMT = tGIVEN + (NYShift+DST_USD);}
if(time_zone_known=="Lon" ){tGMT = tGIVEN + (LondonShift+DST_EUR);}
if(time_zone_known=="Ffm" ){tGMT = tGIVEN + (FfmShift+DST_EUR);}
if(time_zone_known=="Syd" ){tGMT = tGIVEN + (SidneyShift+DST_AUD);}
if(time_zone_known=="Mosc" ){tGMT = tGIVEN + (MoskwaShift+DST_RUS);}
if(time_zone_known=="Tok" ){tGMT = tGIVEN + (TokyoShift);}
// define the required time:
tREQ = NULL;
if(time_zone_required=="GMT" ){tREQ = tGMT;}
if(time_zone_required=="Broker" ){tREQ = tGMT - OffsetBroker.actOffset;}
if(time_zone_required=="NY" ){tREQ = tGMT - (NYShift+DST_USD);}
if(time_zone_required=="Lon" ){tREQ = tGMT - (LondonShift+DST_EUR);}
if(time_zone_required=="Ffm" ){tREQ = tGMT - (FfmShift+DST_EUR);}
if(time_zone_required=="Syd" ){tREQ = tGMT - (SidneyShift+DST_AUD) ;}
if(time_zone_required=="Mosc" ){tREQ = tGMT - (MoskwaShift+DST_RUS);}
if(time_zone_required=="Tok" ){tREQ = tGMT - (TokyoShift);}
return tREQ;
}
// Calculte NY close time:
double TimeZones::ny_daily_close(string symbol, int shift_days, bool print_data=false){
required_close = ny_daily_close_protected(symbol, shift_days, print_data);
return required_close;
}
double TimeZones::ny_daily_close_protected(string symbol, int shift_days, bool print_data=false){
// Get the brokers times for when NY openend today and tomorrow:
datetime time_5pm = iTime(symbol, PERIOD_D1 , 0) - (PeriodSeconds(PERIOD_H1) * 7);
datetime ny_close_in_brokers_time = timezone_conversions("NY", time_5pm, "Broker");
datetime ny_close_time = ny_close_in_brokers_time + PeriodSeconds(PERIOD_D1); // ny close tomorrow
if(TimeCurrent()<ny_close_time){
ny_close_time = ny_close_time - PeriodSeconds(PERIOD_D1); // ny close today
}
// Get the number of hours since NY closed:
int shift = iBarShift(symbol, PERIOD_H1, ny_close_time, false) + 1;
shift = shift + (24 * (shift_days - 1)); // shift days if required:
double ny_close = iClose(symbol,PERIOD_H1, shift);
double br_close = iClose(symbol,PERIOD_H1, 1);
if(print_data==true){
Print("shift ",shift);
Print("time_5pm ",time_5pm);
Print("ny_close_in_brokers_time ",ny_close_in_brokers_time);
Print("ny_close_time ",ny_close_time);
Print("ny_close ", ny_close);
Print("br_close ",br_close);
}
return ny_close;
}
+65
View File
@@ -0,0 +1,65 @@
#property library
#include <Trade/Trade.mqh>
#include <MyLibs/TimeZones.mqh>
class TradingWindow : public CObject{
protected:
TimeZones tz;
bool in_window;
datetime start_time;
datetime end_time;
public:
bool define_window(string t1, string t2, string time_zone, bool plot_range_inp=true);
};
bool TradingWindow::define_window(string t1, string t2, string time_zone, bool plot_range=true){
datetime _t1 = StringToTime(t1);
datetime _t2 = StringToTime(t2);
if(_t1 > _t2){
_t2 = _t2 + PeriodSeconds(PERIOD_D1);
}
int w_duration = (int)(_t2 - _t1);
// window flag
if(TimeCurrent() >= start_time && TimeCurrent() <= end_time){
in_window = true;
}
// define new window
if(TimeCurrent() >= end_time){
in_window = false;
start_time = tz.timezone_conversions(time_zone, StringToTime(t1), "Broker");
if(TimeCurrent()>=start_time){
start_time += PeriodSeconds(PERIOD_D1);
}
end_time = start_time + w_duration;
if(plot_range){
string name = "Start Time" + (string)start_time;
if(start_time>0){
ObjectCreate(NULL, name, OBJ_VLINE, 0, start_time, 0);
ObjectSetInteger(NULL, name,OBJPROP_COLOR, clrBlue);
ObjectSetInteger(NULL, name,OBJPROP_BACK, true);
}
name = "End Time" + (string)end_time;
if(end_time>0){
ObjectCreate(NULL, name, OBJ_VLINE, 0, end_time, 0);
ObjectSetInteger(NULL, name,OBJPROP_COLOR, C'56,108,26');
ObjectSetInteger(NULL, name,OBJPROP_BACK, true);
}
ChartRedraw();
}
}
return in_window;
}