Consolidate Python ignore rules into root gitignore

This commit is contained in:
Hiroaki86
2026-05-27 23:01:28 +09:00
commit fa3394415d
399 changed files with 509103 additions and 0 deletions
+543
View File
@@ -0,0 +1,543 @@
#ifndef SLTP_MANAGER_PANEL_MQH
#define SLTP_MANAGER_PANEL_MQH
#include <Controls/Dialog.mqh>
#include <Controls/Button.mqh>
#include <Controls/Edit.mqh>
#include <Controls/Label.mqh>
#define HIT_SLTP_PANEL_NAME "HIT_SLTP_Manager_Panel"
#define HIT_SLTP_PANEL_WIDTH 620
#define HIT_SLTP_PANEL_HEIGHT 370
#define HIT_SLTP_ROW_HEIGHT 22
#define HIT_SLTP_LABEL_X 15
#define HIT_SLTP_LABEL_WIDTH 125
#define HIT_SLTP_BUTTON_X 150
#define HIT_SLTP_BUTTON_WIDTH 74
#define HIT_SLTP_BUTTON_HEIGHT 26
#define HIT_SLTP_EDIT_X1 240
#define HIT_SLTP_EDIT_X2 330
#define HIT_SLTP_EDIT_X3 420
#define HIT_SLTP_EDIT_X4 510
#define HIT_SLTP_EDIT_WIDTH 80
#define HIT_SLTP_APPLY_WIDTH 90
#define HIT_SLTP_APPLY_HEIGHT 28
#define HIT_SLTP_TITLE_Y 8
#define HIT_SLTP_TITLE_WIDTH 240
#define HIT_SLTP_MASTER_ROW_Y 38
#define HIT_SLTP_BE_ROW_Y 82
#define HIT_SLTP_ELAPSED_ROW_Y 128
#define HIT_SLTP_ACTIVE_ROW_Y 174
#define HIT_SLTP_TP_ROW_Y 220
#define HIT_SLTP_HIGH_VOL_ROW_Y 266
#define HIT_SLTP_APPLY_ROW_Y 302
#define HIT_SLTP_FONT_SIZE 9
#define HIT_SLTP_FONT_STYLE "Arial Black"
#define HIT_SLTP_MASTER_BTN_NAME "HIT_SLTP_MASTER_BTN"
#define HIT_SLTP_BE_BTN_NAME "HIT_SLTP_BE_BTN"
#define HIT_SLTP_ELAPSED_BE_BTN_NAME "HIT_SLTP_ELAPSED_BE_BTN"
#define HIT_SLTP_ACTIVE_TRAIL_BTN_NAME "HIT_SLTP_ACTIVE_TRAIL_BTN"
#define HIT_SLTP_TP_PROGRESS_BTN_NAME "HIT_SLTP_TP_PROGRESS_BTN"
#define HIT_SLTP_HIGH_VOL_BTN_NAME "HIT_SLTP_HIGH_VOL_BTN"
#define HIT_SLTP_APPLY_BTN_NAME "HIT_SLTP_APPLY_BTN"
#define HIT_SLTP_BE_TRIGGER_EDIT_NAME "HIT_SLTP_BE_TRIGGER"
#define HIT_SLTP_BE_BUFFER_EDIT_NAME "HIT_SLTP_BE_BUFFER"
#define HIT_SLTP_ELAPSED_HOURS_EDIT_NAME "HIT_SLTP_ELAPSED_HOURS"
#define HIT_SLTP_ELAPSED_BUFFER_EDIT_NAME "HIT_SLTP_ELAPSED_BUFFER"
#define HIT_SLTP_ACTIVE_START_EDIT_NAME "HIT_SLTP_ACTIVE_START"
#define HIT_SLTP_ACTIVE_OFFSET_EDIT_NAME "HIT_SLTP_ACTIVE_OFFSET"
#define HIT_SLTP_ACTIVE_STEP_TRIGGER_EDIT_NAME "HIT_SLTP_ACTIVE_STEP_TRIGGER"
#define HIT_SLTP_ACTIVE_STEP_MOVE_EDIT_NAME "HIT_SLTP_ACTIVE_STEP_MOVE"
#define HIT_SLTP_TP_TRIGGER_EDIT_NAME "HIT_SLTP_TP_TRIGGER"
#define HIT_SLTP_TP_LOCK_EDIT_NAME "HIT_SLTP_TP_LOCK"
struct SLTPManagerPanelSettings
{
bool manager_enabled;
bool use_breakeven;
double breakeven_trigger_pips;
double breakeven_buffer_pips;
bool use_elapsed_breakeven;
double elapsed_breakeven_hours;
double elapsed_breakeven_buffer_pips;
bool use_active_trailing;
double active_breakeven_pips;
double active_stop_loss_offset_pips;
double active_step_trigger_pips;
double active_step_move_pips;
bool use_tp_progress_stop;
double tp_progress_trigger_percent;
double tp_progress_sl_lock_percent;
bool use_high_volatility_limit;
};
class CSLTPManagerPanel
{
private:
CAppDialog m_panel;
CButton m_button_master;
CButton m_button_breakeven;
CButton m_button_elapsed_breakeven;
CButton m_button_active_trailing;
CButton m_button_tp_progress;
CButton m_button_high_volatility;
CButton m_button_apply;
CEdit m_edit_breakeven_trigger;
CEdit m_edit_breakeven_buffer;
CEdit m_edit_elapsed_hours;
CEdit m_edit_elapsed_buffer;
CEdit m_edit_active_start;
CEdit m_edit_active_offset;
CEdit m_edit_active_step_trigger;
CEdit m_edit_active_step_move;
CEdit m_edit_tp_trigger;
CEdit m_edit_tp_lock;
CLabel m_label_title;
CLabel m_label_master;
CLabel m_label_breakeven;
CLabel m_label_elapsed_breakeven;
CLabel m_label_active_trailing;
CLabel m_label_tp_progress;
CLabel m_label_high_volatility;
CLabel m_label_be_trigger;
CLabel m_label_be_buffer;
CLabel m_label_elapsed_hours;
CLabel m_label_elapsed_buffer;
CLabel m_label_active_start;
CLabel m_label_active_offset;
CLabel m_label_active_step_trigger;
CLabel m_label_active_step_move;
CLabel m_label_tp_trigger;
CLabel m_label_tp_lock;
SLTPManagerPanelSettings m_settings;
public:
void Init(const SLTPManagerPanelSettings &initial_settings)
{
m_settings = initial_settings;
}
bool CreatePanel()
{
const int chart_width = (int)ChartGetInteger(0, CHART_WIDTH_IN_PIXELS);
int panel_x = chart_width - HIT_SLTP_PANEL_WIDTH - 20;
if (panel_x < 10)
panel_x = 10;
const int panel_y = 25;
if (!m_panel.Create(0, HIT_SLTP_PANEL_NAME, 0, panel_x, panel_y,
panel_x + HIT_SLTP_PANEL_WIDTH + 8,
panel_y + HIT_SLTP_PANEL_HEIGHT))
{
Print("SLTP panel create failed: err=", GetLastError());
return false;
}
CreateLabel(m_label_title, "HIT_SLTP_LABEL_TITLE", HIT_SLTP_LABEL_X, HIT_SLTP_TITLE_Y,
HIT_SLTP_TITLE_WIDTH, "HIT SLTP Manager");
CreateLabel(m_label_master, "HIT_SLTP_LABEL_MASTER", HIT_SLTP_LABEL_X, HIT_SLTP_MASTER_ROW_Y,
HIT_SLTP_LABEL_WIDTH, "Manager");
CreateButton(m_button_master, HIT_SLTP_MASTER_BTN_NAME, HIT_SLTP_BUTTON_X, HIT_SLTP_MASTER_ROW_Y,
HIT_SLTP_BUTTON_WIDTH, HIT_SLTP_BUTTON_HEIGHT);
CreateLabel(m_label_breakeven, "HIT_SLTP_LABEL_BE", HIT_SLTP_LABEL_X, HIT_SLTP_BE_ROW_Y,
HIT_SLTP_LABEL_WIDTH, "BreakEven");
CreateButton(m_button_breakeven, HIT_SLTP_BE_BTN_NAME, HIT_SLTP_BUTTON_X, HIT_SLTP_BE_ROW_Y,
HIT_SLTP_BUTTON_WIDTH, HIT_SLTP_BUTTON_HEIGHT);
CreateLabel(m_label_be_trigger, "HIT_SLTP_LABEL_BE_TRG", HIT_SLTP_EDIT_X1,
HIT_SLTP_BE_ROW_Y - HIT_SLTP_ROW_HEIGHT, HIT_SLTP_EDIT_WIDTH, "Trigger");
CreateLabel(m_label_be_buffer, "HIT_SLTP_LABEL_BE_BUF", HIT_SLTP_EDIT_X2,
HIT_SLTP_BE_ROW_Y - HIT_SLTP_ROW_HEIGHT, HIT_SLTP_EDIT_WIDTH, "Buffer");
CreateEdit(m_edit_breakeven_trigger, HIT_SLTP_BE_TRIGGER_EDIT_NAME, HIT_SLTP_EDIT_X1,
HIT_SLTP_BE_ROW_Y, HIT_SLTP_EDIT_WIDTH);
CreateEdit(m_edit_breakeven_buffer, HIT_SLTP_BE_BUFFER_EDIT_NAME, HIT_SLTP_EDIT_X2,
HIT_SLTP_BE_ROW_Y, HIT_SLTP_EDIT_WIDTH);
CreateLabel(m_label_elapsed_breakeven, "HIT_SLTP_LABEL_ELAPSED", HIT_SLTP_LABEL_X,
HIT_SLTP_ELAPSED_ROW_Y, HIT_SLTP_LABEL_WIDTH, "Elapsed BE");
CreateButton(m_button_elapsed_breakeven, HIT_SLTP_ELAPSED_BE_BTN_NAME, HIT_SLTP_BUTTON_X,
HIT_SLTP_ELAPSED_ROW_Y, HIT_SLTP_BUTTON_WIDTH, HIT_SLTP_BUTTON_HEIGHT);
CreateLabel(m_label_elapsed_hours, "HIT_SLTP_LABEL_EL_H", HIT_SLTP_EDIT_X1,
HIT_SLTP_ELAPSED_ROW_Y - HIT_SLTP_ROW_HEIGHT, HIT_SLTP_EDIT_WIDTH, "Hours");
CreateLabel(m_label_elapsed_buffer, "HIT_SLTP_LABEL_EL_BUF", HIT_SLTP_EDIT_X2,
HIT_SLTP_ELAPSED_ROW_Y - HIT_SLTP_ROW_HEIGHT, HIT_SLTP_EDIT_WIDTH, "Buffer");
CreateEdit(m_edit_elapsed_hours, HIT_SLTP_ELAPSED_HOURS_EDIT_NAME, HIT_SLTP_EDIT_X1,
HIT_SLTP_ELAPSED_ROW_Y, HIT_SLTP_EDIT_WIDTH);
CreateEdit(m_edit_elapsed_buffer, HIT_SLTP_ELAPSED_BUFFER_EDIT_NAME, HIT_SLTP_EDIT_X2,
HIT_SLTP_ELAPSED_ROW_Y, HIT_SLTP_EDIT_WIDTH);
CreateLabel(m_label_active_trailing, "HIT_SLTP_LABEL_ACTIVE", HIT_SLTP_LABEL_X,
HIT_SLTP_ACTIVE_ROW_Y, HIT_SLTP_LABEL_WIDTH, "Active Trail");
CreateButton(m_button_active_trailing, HIT_SLTP_ACTIVE_TRAIL_BTN_NAME, HIT_SLTP_BUTTON_X,
HIT_SLTP_ACTIVE_ROW_Y, HIT_SLTP_BUTTON_WIDTH, HIT_SLTP_BUTTON_HEIGHT);
CreateLabel(m_label_active_start, "HIT_SLTP_LABEL_ACT_START", HIT_SLTP_EDIT_X1,
HIT_SLTP_ACTIVE_ROW_Y - HIT_SLTP_ROW_HEIGHT, HIT_SLTP_EDIT_WIDTH, "Start");
CreateLabel(m_label_active_offset, "HIT_SLTP_LABEL_ACT_OFFSET", HIT_SLTP_EDIT_X2,
HIT_SLTP_ACTIVE_ROW_Y - HIT_SLTP_ROW_HEIGHT, HIT_SLTP_EDIT_WIDTH, "Offset");
CreateLabel(m_label_active_step_trigger, "HIT_SLTP_LABEL_ACT_TRG", HIT_SLTP_EDIT_X3,
HIT_SLTP_ACTIVE_ROW_Y - HIT_SLTP_ROW_HEIGHT, HIT_SLTP_EDIT_WIDTH, "StepTrig");
CreateLabel(m_label_active_step_move, "HIT_SLTP_LABEL_ACT_MOVE", HIT_SLTP_EDIT_X4,
HIT_SLTP_ACTIVE_ROW_Y - HIT_SLTP_ROW_HEIGHT, HIT_SLTP_EDIT_WIDTH, "StepMove");
CreateEdit(m_edit_active_start, HIT_SLTP_ACTIVE_START_EDIT_NAME, HIT_SLTP_EDIT_X1,
HIT_SLTP_ACTIVE_ROW_Y, HIT_SLTP_EDIT_WIDTH);
CreateEdit(m_edit_active_offset, HIT_SLTP_ACTIVE_OFFSET_EDIT_NAME, HIT_SLTP_EDIT_X2,
HIT_SLTP_ACTIVE_ROW_Y, HIT_SLTP_EDIT_WIDTH);
CreateEdit(m_edit_active_step_trigger, HIT_SLTP_ACTIVE_STEP_TRIGGER_EDIT_NAME, HIT_SLTP_EDIT_X3,
HIT_SLTP_ACTIVE_ROW_Y, HIT_SLTP_EDIT_WIDTH);
CreateEdit(m_edit_active_step_move, HIT_SLTP_ACTIVE_STEP_MOVE_EDIT_NAME, HIT_SLTP_EDIT_X4,
HIT_SLTP_ACTIVE_ROW_Y, HIT_SLTP_EDIT_WIDTH);
CreateLabel(m_label_tp_progress, "HIT_SLTP_LABEL_TP_PROGRESS", HIT_SLTP_LABEL_X,
HIT_SLTP_TP_ROW_Y, HIT_SLTP_LABEL_WIDTH, "TP Progress");
CreateButton(m_button_tp_progress, HIT_SLTP_TP_PROGRESS_BTN_NAME, HIT_SLTP_BUTTON_X,
HIT_SLTP_TP_ROW_Y, HIT_SLTP_BUTTON_WIDTH, HIT_SLTP_BUTTON_HEIGHT);
CreateLabel(m_label_tp_trigger, "HIT_SLTP_LABEL_TP_TRG", HIT_SLTP_EDIT_X1,
HIT_SLTP_TP_ROW_Y - HIT_SLTP_ROW_HEIGHT, HIT_SLTP_EDIT_WIDTH, "Trig %");
CreateLabel(m_label_tp_lock, "HIT_SLTP_LABEL_TP_LOCK", HIT_SLTP_EDIT_X2,
HIT_SLTP_TP_ROW_Y - HIT_SLTP_ROW_HEIGHT, HIT_SLTP_EDIT_WIDTH, "Lock %");
CreateEdit(m_edit_tp_trigger, HIT_SLTP_TP_TRIGGER_EDIT_NAME, HIT_SLTP_EDIT_X1,
HIT_SLTP_TP_ROW_Y, HIT_SLTP_EDIT_WIDTH);
CreateEdit(m_edit_tp_lock, HIT_SLTP_TP_LOCK_EDIT_NAME, HIT_SLTP_EDIT_X2,
HIT_SLTP_TP_ROW_Y, HIT_SLTP_EDIT_WIDTH);
CreateLabel(m_label_high_volatility, "HIT_SLTP_LABEL_HIGH_VOL", HIT_SLTP_LABEL_X,
HIT_SLTP_HIGH_VOL_ROW_Y, HIT_SLTP_LABEL_WIDTH, "High Vol");
CreateButton(m_button_high_volatility, HIT_SLTP_HIGH_VOL_BTN_NAME, HIT_SLTP_BUTTON_X,
HIT_SLTP_HIGH_VOL_ROW_Y, HIT_SLTP_BUTTON_WIDTH, HIT_SLTP_BUTTON_HEIGHT);
CreateButton(m_button_apply, HIT_SLTP_APPLY_BTN_NAME, HIT_SLTP_EDIT_X4, HIT_SLTP_APPLY_ROW_Y,
HIT_SLTP_APPLY_WIDTH, HIT_SLTP_APPLY_HEIGHT);
m_button_apply.Text("APPLY");
m_button_apply.Color(clrWhite);
m_button_apply.ColorBackground(clrSeaGreen);
m_button_apply.ColorBorder(clrSeaGreen);
RefreshControls();
m_panel.Run();
return true;
}
void Destroy(const int reason)
{
m_panel.Destroy(reason);
}
void SetInitialValues()
{
RefreshControls();
}
bool HandleChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam,
SLTPManagerPanelSettings &applied_settings)
{
m_panel.ChartEvent(id, lparam, dparam, sparam);
if (id != CHARTEVENT_OBJECT_CLICK)
return false;
if (sparam == HIT_SLTP_MASTER_BTN_NAME)
{
m_settings.manager_enabled = !m_settings.manager_enabled;
RefreshButtons();
return false;
}
if (sparam == HIT_SLTP_BE_BTN_NAME)
{
m_settings.use_breakeven = !m_settings.use_breakeven;
if (m_settings.use_breakeven)
m_settings.use_active_trailing = false;
RefreshButtons();
return false;
}
if (sparam == HIT_SLTP_ELAPSED_BE_BTN_NAME)
{
m_settings.use_elapsed_breakeven = !m_settings.use_elapsed_breakeven;
RefreshButtons();
return false;
}
if (sparam == HIT_SLTP_ACTIVE_TRAIL_BTN_NAME)
{
m_settings.use_active_trailing = !m_settings.use_active_trailing;
if (m_settings.use_active_trailing)
m_settings.use_breakeven = false;
RefreshButtons();
return false;
}
if (sparam == HIT_SLTP_TP_PROGRESS_BTN_NAME)
{
m_settings.use_tp_progress_stop = !m_settings.use_tp_progress_stop;
RefreshButtons();
return false;
}
if (sparam == HIT_SLTP_HIGH_VOL_BTN_NAME)
{
m_settings.use_high_volatility_limit = !m_settings.use_high_volatility_limit;
RefreshButtons();
return false;
}
if (sparam == HIT_SLTP_APPLY_BTN_NAME)
{
if (!ReadInputs())
return false;
applied_settings = m_settings;
Print("HIT SLTP panel settings applied.");
return true;
}
return false;
}
private:
void CreateButton(CButton &button,
const string name,
const int x,
const int y,
const int width,
const int height)
{
if (!button.Create(0, name, 0, x, y, 0, 0))
{
Print("SLTP button create failed: ", name, " err=", GetLastError());
return;
}
button.Width(width);
button.Height(height);
button.Font(HIT_SLTP_FONT_STYLE);
button.FontSize(HIT_SLTP_FONT_SIZE);
m_panel.Add(button);
}
void CreateLabel(CLabel &label,
const string name,
const int x,
const int y,
const int width,
const string text)
{
if (!label.Create(0, name, 0, x, y, 0, 0))
{
Print("SLTP label create failed: ", name, " err=", GetLastError());
return;
}
label.Width(width);
label.Height(HIT_SLTP_ROW_HEIGHT);
label.Text(text);
label.Font(HIT_SLTP_FONT_STYLE);
label.FontSize(HIT_SLTP_FONT_SIZE);
label.Color(clrDimGray);
label.ColorBackground(clrDimGray);
label.ColorBorder(clrDimGray);
m_panel.Add(label);
}
void CreateEdit(CEdit &edit,
const string name,
const int x,
const int y,
const int width)
{
if (!edit.Create(0, name, 0, x, y, 0, 0))
{
Print("SLTP edit create failed: ", name, " err=", GetLastError());
return;
}
edit.Width(width);
edit.Height(HIT_SLTP_ROW_HEIGHT);
edit.Font(HIT_SLTP_FONT_STYLE);
edit.FontSize(HIT_SLTP_FONT_SIZE);
edit.Color(clrDimGray);
edit.ColorBackground(clrWhite);
edit.ColorBorder(clrDimGray);
m_panel.Add(edit);
}
void RefreshControls()
{
RefreshButtons();
m_edit_breakeven_trigger.Text(DoubleToString(m_settings.breakeven_trigger_pips, 1));
m_edit_breakeven_buffer.Text(DoubleToString(m_settings.breakeven_buffer_pips, 1));
m_edit_elapsed_hours.Text(DoubleToString(m_settings.elapsed_breakeven_hours, 1));
m_edit_elapsed_buffer.Text(DoubleToString(m_settings.elapsed_breakeven_buffer_pips, 1));
m_edit_active_start.Text(DoubleToString(m_settings.active_breakeven_pips, 1));
m_edit_active_offset.Text(DoubleToString(m_settings.active_stop_loss_offset_pips, 1));
m_edit_active_step_trigger.Text(DoubleToString(m_settings.active_step_trigger_pips, 1));
m_edit_active_step_move.Text(DoubleToString(m_settings.active_step_move_pips, 1));
m_edit_tp_trigger.Text(DoubleToString(m_settings.tp_progress_trigger_percent, 1));
m_edit_tp_lock.Text(DoubleToString(m_settings.tp_progress_sl_lock_percent, 1));
}
void RefreshButtons()
{
ApplyToggleButton(m_button_master, m_settings.manager_enabled, "ON", "OFF");
ApplyToggleButton(m_button_breakeven, m_settings.use_breakeven, "ON", "OFF");
ApplyToggleButton(m_button_elapsed_breakeven, m_settings.use_elapsed_breakeven, "ON", "OFF");
ApplyToggleButton(m_button_active_trailing, m_settings.use_active_trailing, "ON", "OFF");
ApplyToggleButton(m_button_tp_progress, m_settings.use_tp_progress_stop, "ON", "OFF");
ApplyToggleButton(m_button_high_volatility, m_settings.use_high_volatility_limit, "ON", "OFF");
}
void ApplyToggleButton(CButton &button,
const bool enabled,
const string on_text,
const string off_text)
{
if (enabled)
{
button.Text(on_text);
button.Color(clrWhite);
button.ColorBackground(clrRoyalBlue);
button.ColorBorder(clrRoyalBlue);
}
else
{
button.Text(off_text);
button.Color(clrRoyalBlue);
button.ColorBackground(clrWhite);
button.ColorBorder(clrRoyalBlue);
}
}
bool ReadInputs()
{
bool ok = true;
ok = ReadDoubleValue(m_edit_breakeven_trigger, "BreakEven Trigger", 0.0, 10000.0,
m_settings.breakeven_trigger_pips, m_settings.breakeven_trigger_pips) && ok;
ok = ReadDoubleValue(m_edit_breakeven_buffer, "BreakEven Buffer", 0.0, 10000.0,
m_settings.breakeven_buffer_pips, m_settings.breakeven_buffer_pips) && ok;
ok = ReadDoubleValue(m_edit_elapsed_hours, "Elapsed BE Hours", 0.0, 10000.0,
m_settings.elapsed_breakeven_hours, m_settings.elapsed_breakeven_hours) && ok;
ok = ReadDoubleValue(m_edit_elapsed_buffer, "Elapsed BE Buffer", 0.0, 10000.0,
m_settings.elapsed_breakeven_buffer_pips, m_settings.elapsed_breakeven_buffer_pips) && ok;
ok = ReadDoubleValue(m_edit_active_start, "Active Trail Start", 0.0, 10000.0,
m_settings.active_breakeven_pips, m_settings.active_breakeven_pips) && ok;
ok = ReadDoubleValue(m_edit_active_offset, "Active Trail Offset", 0.0, 10000.0,
m_settings.active_stop_loss_offset_pips, m_settings.active_stop_loss_offset_pips) && ok;
ok = ReadDoubleValue(m_edit_active_step_trigger, "Active Trail Step Trigger", 0.1, 10000.0,
m_settings.active_step_trigger_pips, m_settings.active_step_trigger_pips) && ok;
ok = ReadDoubleValue(m_edit_active_step_move, "Active Trail Step Move", 0.1, 10000.0,
m_settings.active_step_move_pips, m_settings.active_step_move_pips) && ok;
ok = ReadDoubleValue(m_edit_tp_trigger, "TP Progress Trigger", 0.1, 100.0,
m_settings.tp_progress_trigger_percent, m_settings.tp_progress_trigger_percent) && ok;
ok = ReadDoubleValue(m_edit_tp_lock, "TP Progress Lock", 0.0, 100.0,
m_settings.tp_progress_sl_lock_percent, m_settings.tp_progress_sl_lock_percent) && ok;
if (m_settings.use_breakeven && m_settings.use_active_trailing)
{
MessageBox("BreakEven and Active Trail cannot both be enabled.", "SLTP panel error", MB_ICONERROR);
m_settings.use_active_trailing = false;
RefreshButtons();
ok = false;
}
if (!ok)
RefreshControls();
return ok;
}
bool ReadDoubleValue(CEdit &edit,
const string label,
const double min_value,
const double max_value,
const double default_value,
double &target)
{
const string text = edit.Text();
if (!IsNumericText(text))
{
ShowValueError(edit, label, min_value, max_value, default_value, target);
return false;
}
const double value = StringToDouble(text);
if (value < min_value || value > max_value)
{
ShowValueError(edit, label, min_value, max_value, default_value, target);
return false;
}
target = value;
return true;
}
void ShowValueError(CEdit &edit,
const string label,
const double min_value,
const double max_value,
const double default_value,
double &target)
{
MessageBox(label + " must be between " + DoubleToString(min_value, 1) +
" and " + DoubleToString(max_value, 1) + ".",
"SLTP panel error",
MB_ICONERROR);
edit.Text(DoubleToString(default_value, 1));
target = default_value;
}
bool IsNumericText(const string text)
{
bool has_digit = false;
bool has_dot = false;
bool seen_value_char = false;
const int length = StringLen(text);
for (int i = 0; i < length; ++i)
{
const ushort ch = StringGetCharacter(text, i);
if (ch == 32 || ch == 9)
continue;
if (ch >= 48 && ch <= 57)
{
has_digit = true;
seen_value_char = true;
continue;
}
if (ch == 46 && !has_dot)
{
has_dot = true;
seen_value_char = true;
continue;
}
if ((ch == 43 || ch == 45) && !seen_value_char)
{
seen_value_char = true;
continue;
}
return false;
}
return has_digit;
}
};
#endif
@@ -0,0 +1,494 @@
#ifndef SLTP_MANAGER_PANEL_MQH
#define SLTP_MANAGER_PANEL_MQH
#include <Controls/Dialog.mqh>
#include <Controls/Button.mqh>
#include <Controls/Edit.mqh>
#include <Controls/Label.mqh>
#define HIT_SLTP_PANEL_NAME "HIT_SLTP_Manager_Panel"
#define HIT_SLTP_PANEL_WIDTH 500
#define HIT_SLTP_PANEL_HEIGHT 310
#define HIT_SLTP_ROW_HEIGHT 18
#define HIT_SLTP_LABEL_X 15
#define HIT_SLTP_BUTTON_X 15
#define HIT_SLTP_EDIT_X1 150
#define HIT_SLTP_EDIT_X2 235
#define HIT_SLTP_EDIT_X3 320
#define HIT_SLTP_EDIT_X4 405
#define HIT_SLTP_FONT_SIZE 9
#define HIT_SLTP_FONT_STYLE "Arial Black"
#define HIT_SLTP_MASTER_BTN_NAME "HIT_SLTP_MASTER_BTN"
#define HIT_SLTP_BE_BTN_NAME "HIT_SLTP_BE_BTN"
#define HIT_SLTP_ELAPSED_BE_BTN_NAME "HIT_SLTP_ELAPSED_BE_BTN"
#define HIT_SLTP_ACTIVE_TRAIL_BTN_NAME "HIT_SLTP_ACTIVE_TRAIL_BTN"
#define HIT_SLTP_TP_PROGRESS_BTN_NAME "HIT_SLTP_TP_PROGRESS_BTN"
#define HIT_SLTP_HIGH_VOL_BTN_NAME "HIT_SLTP_HIGH_VOL_BTN"
#define HIT_SLTP_APPLY_BTN_NAME "HIT_SLTP_APPLY_BTN"
#define HIT_SLTP_BE_TRIGGER_EDIT_NAME "HIT_SLTP_BE_TRIGGER"
#define HIT_SLTP_BE_BUFFER_EDIT_NAME "HIT_SLTP_BE_BUFFER"
#define HIT_SLTP_ELAPSED_HOURS_EDIT_NAME "HIT_SLTP_ELAPSED_HOURS"
#define HIT_SLTP_ELAPSED_BUFFER_EDIT_NAME "HIT_SLTP_ELAPSED_BUFFER"
#define HIT_SLTP_ACTIVE_START_EDIT_NAME "HIT_SLTP_ACTIVE_START"
#define HIT_SLTP_ACTIVE_OFFSET_EDIT_NAME "HIT_SLTP_ACTIVE_OFFSET"
#define HIT_SLTP_ACTIVE_STEP_TRIGGER_EDIT_NAME "HIT_SLTP_ACTIVE_STEP_TRIGGER"
#define HIT_SLTP_ACTIVE_STEP_MOVE_EDIT_NAME "HIT_SLTP_ACTIVE_STEP_MOVE"
#define HIT_SLTP_TP_TRIGGER_EDIT_NAME "HIT_SLTP_TP_TRIGGER"
#define HIT_SLTP_TP_LOCK_EDIT_NAME "HIT_SLTP_TP_LOCK"
struct SLTPManagerPanelSettings
{
bool manager_enabled;
bool use_breakeven;
double breakeven_trigger_pips;
double breakeven_buffer_pips;
bool use_elapsed_breakeven;
double elapsed_breakeven_hours;
double elapsed_breakeven_buffer_pips;
bool use_active_trailing;
double active_breakeven_pips;
double active_stop_loss_offset_pips;
double active_step_trigger_pips;
double active_step_move_pips;
bool use_tp_progress_stop;
double tp_progress_trigger_percent;
double tp_progress_sl_lock_percent;
bool use_high_volatility_limit;
};
class CSLTPManagerPanel
{
private:
CAppDialog m_panel;
CButton m_button_master;
CButton m_button_breakeven;
CButton m_button_elapsed_breakeven;
CButton m_button_active_trailing;
CButton m_button_tp_progress;
CButton m_button_high_volatility;
CButton m_button_apply;
CEdit m_edit_breakeven_trigger;
CEdit m_edit_breakeven_buffer;
CEdit m_edit_elapsed_hours;
CEdit m_edit_elapsed_buffer;
CEdit m_edit_active_start;
CEdit m_edit_active_offset;
CEdit m_edit_active_step_trigger;
CEdit m_edit_active_step_move;
CEdit m_edit_tp_trigger;
CEdit m_edit_tp_lock;
CLabel m_label_title;
CLabel m_label_master;
CLabel m_label_breakeven;
CLabel m_label_elapsed_breakeven;
CLabel m_label_active_trailing;
CLabel m_label_tp_progress;
CLabel m_label_high_volatility;
CLabel m_label_be_trigger;
CLabel m_label_be_buffer;
CLabel m_label_elapsed_hours;
CLabel m_label_elapsed_buffer;
CLabel m_label_active_start;
CLabel m_label_active_offset;
CLabel m_label_active_step_trigger;
CLabel m_label_active_step_move;
CLabel m_label_tp_trigger;
CLabel m_label_tp_lock;
SLTPManagerPanelSettings m_settings;
public:
void Init(const SLTPManagerPanelSettings &initial_settings)
{
m_settings = initial_settings;
}
bool CreatePanel()
{
const int chart_width = (int)ChartGetInteger(0, CHART_WIDTH_IN_PIXELS);
int panel_x = chart_width - HIT_SLTP_PANEL_WIDTH - 20;
if (panel_x < 10)
panel_x = 10;
const int panel_y = 25;
if (!m_panel.Create(0, HIT_SLTP_PANEL_NAME, 0, panel_x, panel_y,
panel_x + HIT_SLTP_PANEL_WIDTH + 8,
panel_y + HIT_SLTP_PANEL_HEIGHT))
{
Print("SLTP panel create failed: err=", GetLastError());
return false;
}
CreateLabel(m_label_title, "HIT_SLTP_LABEL_TITLE", HIT_SLTP_LABEL_X, 8, 170, "HIT SLTP Manager");
CreateLabel(m_label_master, "HIT_SLTP_LABEL_MASTER", HIT_SLTP_LABEL_X, 34, 110, "Manager");
CreateButton(m_button_master, HIT_SLTP_MASTER_BTN_NAME, HIT_SLTP_BUTTON_X + 70, 32, 58, 22);
CreateLabel(m_label_breakeven, "HIT_SLTP_LABEL_BE", HIT_SLTP_LABEL_X, 64, 110, "BreakEven");
CreateButton(m_button_breakeven, HIT_SLTP_BE_BTN_NAME, HIT_SLTP_BUTTON_X + 70, 62, 58, 22);
CreateLabel(m_label_be_trigger, "HIT_SLTP_LABEL_BE_TRG", HIT_SLTP_EDIT_X1, 48, 60, "Trigger");
CreateLabel(m_label_be_buffer, "HIT_SLTP_LABEL_BE_BUF", HIT_SLTP_EDIT_X2, 48, 60, "Buffer");
CreateEdit(m_edit_breakeven_trigger, HIT_SLTP_BE_TRIGGER_EDIT_NAME, HIT_SLTP_EDIT_X1, 64, 65);
CreateEdit(m_edit_breakeven_buffer, HIT_SLTP_BE_BUFFER_EDIT_NAME, HIT_SLTP_EDIT_X2, 64, 65);
CreateLabel(m_label_elapsed_breakeven, "HIT_SLTP_LABEL_ELAPSED", HIT_SLTP_LABEL_X, 98, 110, "Elapsed BE");
CreateButton(m_button_elapsed_breakeven, HIT_SLTP_ELAPSED_BE_BTN_NAME, HIT_SLTP_BUTTON_X + 70, 96, 58, 22);
CreateLabel(m_label_elapsed_hours, "HIT_SLTP_LABEL_EL_H", HIT_SLTP_EDIT_X1, 82, 60, "Hours");
CreateLabel(m_label_elapsed_buffer, "HIT_SLTP_LABEL_EL_BUF", HIT_SLTP_EDIT_X2, 82, 60, "Buffer");
CreateEdit(m_edit_elapsed_hours, HIT_SLTP_ELAPSED_HOURS_EDIT_NAME, HIT_SLTP_EDIT_X1, 98, 65);
CreateEdit(m_edit_elapsed_buffer, HIT_SLTP_ELAPSED_BUFFER_EDIT_NAME, HIT_SLTP_EDIT_X2, 98, 65);
CreateLabel(m_label_active_trailing, "HIT_SLTP_LABEL_ACTIVE", HIT_SLTP_LABEL_X, 132, 110, "Active Trail");
CreateButton(m_button_active_trailing, HIT_SLTP_ACTIVE_TRAIL_BTN_NAME, HIT_SLTP_BUTTON_X + 70, 130, 58, 22);
CreateLabel(m_label_active_start, "HIT_SLTP_LABEL_ACT_START", HIT_SLTP_EDIT_X1, 116, 60, "Start");
CreateLabel(m_label_active_offset, "HIT_SLTP_LABEL_ACT_OFFSET", HIT_SLTP_EDIT_X2, 116, 60, "Offset");
CreateLabel(m_label_active_step_trigger, "HIT_SLTP_LABEL_ACT_TRG", HIT_SLTP_EDIT_X3, 116, 70, "StepTrig");
CreateLabel(m_label_active_step_move, "HIT_SLTP_LABEL_ACT_MOVE", HIT_SLTP_EDIT_X4, 116, 70, "StepMove");
CreateEdit(m_edit_active_start, HIT_SLTP_ACTIVE_START_EDIT_NAME, HIT_SLTP_EDIT_X1, 132, 65);
CreateEdit(m_edit_active_offset, HIT_SLTP_ACTIVE_OFFSET_EDIT_NAME, HIT_SLTP_EDIT_X2, 132, 65);
CreateEdit(m_edit_active_step_trigger, HIT_SLTP_ACTIVE_STEP_TRIGGER_EDIT_NAME, HIT_SLTP_EDIT_X3, 132, 65);
CreateEdit(m_edit_active_step_move, HIT_SLTP_ACTIVE_STEP_MOVE_EDIT_NAME, HIT_SLTP_EDIT_X4, 132, 65);
CreateLabel(m_label_tp_progress, "HIT_SLTP_LABEL_TP_PROGRESS", HIT_SLTP_LABEL_X, 166, 110, "TP Progress");
CreateButton(m_button_tp_progress, HIT_SLTP_TP_PROGRESS_BTN_NAME, HIT_SLTP_BUTTON_X + 70, 164, 58, 22);
CreateLabel(m_label_tp_trigger, "HIT_SLTP_LABEL_TP_TRG", HIT_SLTP_EDIT_X1, 150, 60, "Trig %");
CreateLabel(m_label_tp_lock, "HIT_SLTP_LABEL_TP_LOCK", HIT_SLTP_EDIT_X2, 150, 60, "Lock %");
CreateEdit(m_edit_tp_trigger, HIT_SLTP_TP_TRIGGER_EDIT_NAME, HIT_SLTP_EDIT_X1, 166, 65);
CreateEdit(m_edit_tp_lock, HIT_SLTP_TP_LOCK_EDIT_NAME, HIT_SLTP_EDIT_X2, 166, 65);
CreateLabel(m_label_high_volatility, "HIT_SLTP_LABEL_HIGH_VOL", HIT_SLTP_LABEL_X, 200, 110, "High Vol");
CreateButton(m_button_high_volatility, HIT_SLTP_HIGH_VOL_BTN_NAME, HIT_SLTP_BUTTON_X + 70, 198, 58, 22);
CreateButton(m_button_apply, HIT_SLTP_APPLY_BTN_NAME, HIT_SLTP_EDIT_X4, 246, 70, 26);
m_button_apply.Text("APPLY");
m_button_apply.Color(clrWhite);
m_button_apply.ColorBackground(clrSeaGreen);
m_button_apply.ColorBorder(clrSeaGreen);
RefreshControls();
m_panel.Run();
return true;
}
void Destroy(const int reason)
{
m_panel.Destroy(reason);
}
void SetInitialValues()
{
RefreshControls();
}
bool HandleChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam,
SLTPManagerPanelSettings &applied_settings)
{
m_panel.ChartEvent(id, lparam, dparam, sparam);
if (id != CHARTEVENT_OBJECT_CLICK)
return false;
if (sparam == HIT_SLTP_MASTER_BTN_NAME)
{
m_settings.manager_enabled = !m_settings.manager_enabled;
RefreshButtons();
return false;
}
if (sparam == HIT_SLTP_BE_BTN_NAME)
{
m_settings.use_breakeven = !m_settings.use_breakeven;
if (m_settings.use_breakeven)
m_settings.use_active_trailing = false;
RefreshButtons();
return false;
}
if (sparam == HIT_SLTP_ELAPSED_BE_BTN_NAME)
{
m_settings.use_elapsed_breakeven = !m_settings.use_elapsed_breakeven;
RefreshButtons();
return false;
}
if (sparam == HIT_SLTP_ACTIVE_TRAIL_BTN_NAME)
{
m_settings.use_active_trailing = !m_settings.use_active_trailing;
if (m_settings.use_active_trailing)
m_settings.use_breakeven = false;
RefreshButtons();
return false;
}
if (sparam == HIT_SLTP_TP_PROGRESS_BTN_NAME)
{
m_settings.use_tp_progress_stop = !m_settings.use_tp_progress_stop;
RefreshButtons();
return false;
}
if (sparam == HIT_SLTP_HIGH_VOL_BTN_NAME)
{
m_settings.use_high_volatility_limit = !m_settings.use_high_volatility_limit;
RefreshButtons();
return false;
}
if (sparam == HIT_SLTP_APPLY_BTN_NAME)
{
if (!ReadInputs())
return false;
applied_settings = m_settings;
Print("HIT SLTP panel settings applied.");
return true;
}
return false;
}
private:
void CreateButton(CButton &button,
const string name,
const int x,
const int y,
const int width,
const int height)
{
if (!button.Create(0, name, 0, x, y, 0, 0))
{
Print("SLTP button create failed: ", name, " err=", GetLastError());
return;
}
button.Width(width);
button.Height(height);
button.Font(HIT_SLTP_FONT_STYLE);
button.FontSize(HIT_SLTP_FONT_SIZE);
m_panel.Add(button);
}
void CreateLabel(CLabel &label,
const string name,
const int x,
const int y,
const int width,
const string text)
{
if (!label.Create(0, name, 0, x, y, 0, 0))
{
Print("SLTP label create failed: ", name, " err=", GetLastError());
return;
}
label.Width(width);
label.Height(HIT_SLTP_ROW_HEIGHT);
label.Text(text);
label.Font(HIT_SLTP_FONT_STYLE);
label.FontSize(HIT_SLTP_FONT_SIZE);
label.Color(clrDimGray);
label.ColorBackground(clrDimGray);
label.ColorBorder(clrDimGray);
m_panel.Add(label);
}
void CreateEdit(CEdit &edit,
const string name,
const int x,
const int y,
const int width)
{
if (!edit.Create(0, name, 0, x, y, 0, 0))
{
Print("SLTP edit create failed: ", name, " err=", GetLastError());
return;
}
edit.Width(width);
edit.Height(HIT_SLTP_ROW_HEIGHT);
edit.Font(HIT_SLTP_FONT_STYLE);
edit.FontSize(HIT_SLTP_FONT_SIZE);
edit.Color(clrDimGray);
edit.ColorBackground(clrWhite);
edit.ColorBorder(clrDimGray);
m_panel.Add(edit);
}
void RefreshControls()
{
RefreshButtons();
m_edit_breakeven_trigger.Text(DoubleToString(m_settings.breakeven_trigger_pips, 1));
m_edit_breakeven_buffer.Text(DoubleToString(m_settings.breakeven_buffer_pips, 1));
m_edit_elapsed_hours.Text(DoubleToString(m_settings.elapsed_breakeven_hours, 1));
m_edit_elapsed_buffer.Text(DoubleToString(m_settings.elapsed_breakeven_buffer_pips, 1));
m_edit_active_start.Text(DoubleToString(m_settings.active_breakeven_pips, 1));
m_edit_active_offset.Text(DoubleToString(m_settings.active_stop_loss_offset_pips, 1));
m_edit_active_step_trigger.Text(DoubleToString(m_settings.active_step_trigger_pips, 1));
m_edit_active_step_move.Text(DoubleToString(m_settings.active_step_move_pips, 1));
m_edit_tp_trigger.Text(DoubleToString(m_settings.tp_progress_trigger_percent, 1));
m_edit_tp_lock.Text(DoubleToString(m_settings.tp_progress_sl_lock_percent, 1));
}
void RefreshButtons()
{
ApplyToggleButton(m_button_master, m_settings.manager_enabled, "ON", "OFF");
ApplyToggleButton(m_button_breakeven, m_settings.use_breakeven, "ON", "OFF");
ApplyToggleButton(m_button_elapsed_breakeven, m_settings.use_elapsed_breakeven, "ON", "OFF");
ApplyToggleButton(m_button_active_trailing, m_settings.use_active_trailing, "ON", "OFF");
ApplyToggleButton(m_button_tp_progress, m_settings.use_tp_progress_stop, "ON", "OFF");
ApplyToggleButton(m_button_high_volatility, m_settings.use_high_volatility_limit, "ON", "OFF");
}
void ApplyToggleButton(CButton &button,
const bool enabled,
const string on_text,
const string off_text)
{
if (enabled)
{
button.Text(on_text);
button.Color(clrWhite);
button.ColorBackground(clrRoyalBlue);
button.ColorBorder(clrRoyalBlue);
}
else
{
button.Text(off_text);
button.Color(clrRoyalBlue);
button.ColorBackground(clrWhite);
button.ColorBorder(clrRoyalBlue);
}
}
bool ReadInputs()
{
bool ok = true;
ok = ReadDoubleValue(m_edit_breakeven_trigger, "BreakEven Trigger", 0.0, 10000.0,
m_settings.breakeven_trigger_pips, m_settings.breakeven_trigger_pips) && ok;
ok = ReadDoubleValue(m_edit_breakeven_buffer, "BreakEven Buffer", 0.0, 10000.0,
m_settings.breakeven_buffer_pips, m_settings.breakeven_buffer_pips) && ok;
ok = ReadDoubleValue(m_edit_elapsed_hours, "Elapsed BE Hours", 0.0, 10000.0,
m_settings.elapsed_breakeven_hours, m_settings.elapsed_breakeven_hours) && ok;
ok = ReadDoubleValue(m_edit_elapsed_buffer, "Elapsed BE Buffer", 0.0, 10000.0,
m_settings.elapsed_breakeven_buffer_pips, m_settings.elapsed_breakeven_buffer_pips) && ok;
ok = ReadDoubleValue(m_edit_active_start, "Active Trail Start", 0.0, 10000.0,
m_settings.active_breakeven_pips, m_settings.active_breakeven_pips) && ok;
ok = ReadDoubleValue(m_edit_active_offset, "Active Trail Offset", 0.0, 10000.0,
m_settings.active_stop_loss_offset_pips, m_settings.active_stop_loss_offset_pips) && ok;
ok = ReadDoubleValue(m_edit_active_step_trigger, "Active Trail Step Trigger", 0.1, 10000.0,
m_settings.active_step_trigger_pips, m_settings.active_step_trigger_pips) && ok;
ok = ReadDoubleValue(m_edit_active_step_move, "Active Trail Step Move", 0.1, 10000.0,
m_settings.active_step_move_pips, m_settings.active_step_move_pips) && ok;
ok = ReadDoubleValue(m_edit_tp_trigger, "TP Progress Trigger", 0.1, 100.0,
m_settings.tp_progress_trigger_percent, m_settings.tp_progress_trigger_percent) && ok;
ok = ReadDoubleValue(m_edit_tp_lock, "TP Progress Lock", 0.0, 100.0,
m_settings.tp_progress_sl_lock_percent, m_settings.tp_progress_sl_lock_percent) && ok;
if (m_settings.use_breakeven && m_settings.use_active_trailing)
{
MessageBox("BreakEven and Active Trail cannot both be enabled.", "SLTP panel error", MB_ICONERROR);
m_settings.use_active_trailing = false;
RefreshButtons();
ok = false;
}
if (!ok)
RefreshControls();
return ok;
}
bool ReadDoubleValue(CEdit &edit,
const string label,
const double min_value,
const double max_value,
const double default_value,
double &target)
{
const string text = edit.Text();
if (!IsNumericText(text))
{
ShowValueError(edit, label, min_value, max_value, default_value, target);
return false;
}
const double value = StringToDouble(text);
if (value < min_value || value > max_value)
{
ShowValueError(edit, label, min_value, max_value, default_value, target);
return false;
}
target = value;
return true;
}
void ShowValueError(CEdit &edit,
const string label,
const double min_value,
const double max_value,
const double default_value,
double &target)
{
MessageBox(label + " must be between " + DoubleToString(min_value, 1) +
" and " + DoubleToString(max_value, 1) + ".",
"SLTP panel error",
MB_ICONERROR);
edit.Text(DoubleToString(default_value, 1));
target = default_value;
}
bool IsNumericText(const string text)
{
bool has_digit = false;
bool has_dot = false;
bool seen_value_char = false;
const int length = StringLen(text);
for (int i = 0; i < length; ++i)
{
const ushort ch = StringGetCharacter(text, i);
if (ch == 32 || ch == 9)
continue;
if (ch >= 48 && ch <= 57)
{
has_digit = true;
seen_value_char = true;
continue;
}
if (ch == 46 && !has_dot)
{
has_dot = true;
seen_value_char = true;
continue;
}
if ((ch == 43 || ch == 45) && !seen_value_char)
{
seen_value_char = true;
continue;
}
return false;
}
return has_digit;
}
};
#endif
@@ -0,0 +1,543 @@
#ifndef SLTP_MANAGER_PANEL_MQH
#define SLTP_MANAGER_PANEL_MQH
#include <Controls/Dialog.mqh>
#include <Controls/Button.mqh>
#include <Controls/Edit.mqh>
#include <Controls/Label.mqh>
#define HIT_SLTP_PANEL_NAME "HIT_SLTP_Manager_Panel"
#define HIT_SLTP_PANEL_WIDTH 620
#define HIT_SLTP_PANEL_HEIGHT 370
#define HIT_SLTP_ROW_HEIGHT 22
#define HIT_SLTP_LABEL_X 15
#define HIT_SLTP_LABEL_WIDTH 125
#define HIT_SLTP_BUTTON_X 150
#define HIT_SLTP_BUTTON_WIDTH 74
#define HIT_SLTP_BUTTON_HEIGHT 26
#define HIT_SLTP_EDIT_X1 240
#define HIT_SLTP_EDIT_X2 330
#define HIT_SLTP_EDIT_X3 420
#define HIT_SLTP_EDIT_X4 510
#define HIT_SLTP_EDIT_WIDTH 80
#define HIT_SLTP_APPLY_WIDTH 90
#define HIT_SLTP_APPLY_HEIGHT 28
#define HIT_SLTP_TITLE_Y 8
#define HIT_SLTP_TITLE_WIDTH 240
#define HIT_SLTP_MASTER_ROW_Y 38
#define HIT_SLTP_BE_ROW_Y 82
#define HIT_SLTP_ELAPSED_ROW_Y 128
#define HIT_SLTP_ACTIVE_ROW_Y 174
#define HIT_SLTP_TP_ROW_Y 220
#define HIT_SLTP_HIGH_VOL_ROW_Y 266
#define HIT_SLTP_APPLY_ROW_Y 312
#define HIT_SLTP_FONT_SIZE 9
#define HIT_SLTP_FONT_STYLE "Arial Black"
#define HIT_SLTP_MASTER_BTN_NAME "HIT_SLTP_MASTER_BTN"
#define HIT_SLTP_BE_BTN_NAME "HIT_SLTP_BE_BTN"
#define HIT_SLTP_ELAPSED_BE_BTN_NAME "HIT_SLTP_ELAPSED_BE_BTN"
#define HIT_SLTP_ACTIVE_TRAIL_BTN_NAME "HIT_SLTP_ACTIVE_TRAIL_BTN"
#define HIT_SLTP_TP_PROGRESS_BTN_NAME "HIT_SLTP_TP_PROGRESS_BTN"
#define HIT_SLTP_HIGH_VOL_BTN_NAME "HIT_SLTP_HIGH_VOL_BTN"
#define HIT_SLTP_APPLY_BTN_NAME "HIT_SLTP_APPLY_BTN"
#define HIT_SLTP_BE_TRIGGER_EDIT_NAME "HIT_SLTP_BE_TRIGGER"
#define HIT_SLTP_BE_BUFFER_EDIT_NAME "HIT_SLTP_BE_BUFFER"
#define HIT_SLTP_ELAPSED_HOURS_EDIT_NAME "HIT_SLTP_ELAPSED_HOURS"
#define HIT_SLTP_ELAPSED_BUFFER_EDIT_NAME "HIT_SLTP_ELAPSED_BUFFER"
#define HIT_SLTP_ACTIVE_START_EDIT_NAME "HIT_SLTP_ACTIVE_START"
#define HIT_SLTP_ACTIVE_OFFSET_EDIT_NAME "HIT_SLTP_ACTIVE_OFFSET"
#define HIT_SLTP_ACTIVE_STEP_TRIGGER_EDIT_NAME "HIT_SLTP_ACTIVE_STEP_TRIGGER"
#define HIT_SLTP_ACTIVE_STEP_MOVE_EDIT_NAME "HIT_SLTP_ACTIVE_STEP_MOVE"
#define HIT_SLTP_TP_TRIGGER_EDIT_NAME "HIT_SLTP_TP_TRIGGER"
#define HIT_SLTP_TP_LOCK_EDIT_NAME "HIT_SLTP_TP_LOCK"
struct SLTPManagerPanelSettings
{
bool manager_enabled;
bool use_breakeven;
double breakeven_trigger_pips;
double breakeven_buffer_pips;
bool use_elapsed_breakeven;
double elapsed_breakeven_hours;
double elapsed_breakeven_buffer_pips;
bool use_active_trailing;
double active_breakeven_pips;
double active_stop_loss_offset_pips;
double active_step_trigger_pips;
double active_step_move_pips;
bool use_tp_progress_stop;
double tp_progress_trigger_percent;
double tp_progress_sl_lock_percent;
bool use_high_volatility_limit;
};
class CSLTPManagerPanel
{
private:
CAppDialog m_panel;
CButton m_button_master;
CButton m_button_breakeven;
CButton m_button_elapsed_breakeven;
CButton m_button_active_trailing;
CButton m_button_tp_progress;
CButton m_button_high_volatility;
CButton m_button_apply;
CEdit m_edit_breakeven_trigger;
CEdit m_edit_breakeven_buffer;
CEdit m_edit_elapsed_hours;
CEdit m_edit_elapsed_buffer;
CEdit m_edit_active_start;
CEdit m_edit_active_offset;
CEdit m_edit_active_step_trigger;
CEdit m_edit_active_step_move;
CEdit m_edit_tp_trigger;
CEdit m_edit_tp_lock;
CLabel m_label_title;
CLabel m_label_master;
CLabel m_label_breakeven;
CLabel m_label_elapsed_breakeven;
CLabel m_label_active_trailing;
CLabel m_label_tp_progress;
CLabel m_label_high_volatility;
CLabel m_label_be_trigger;
CLabel m_label_be_buffer;
CLabel m_label_elapsed_hours;
CLabel m_label_elapsed_buffer;
CLabel m_label_active_start;
CLabel m_label_active_offset;
CLabel m_label_active_step_trigger;
CLabel m_label_active_step_move;
CLabel m_label_tp_trigger;
CLabel m_label_tp_lock;
SLTPManagerPanelSettings m_settings;
public:
void Init(const SLTPManagerPanelSettings &initial_settings)
{
m_settings = initial_settings;
}
bool CreatePanel()
{
const int chart_width = (int)ChartGetInteger(0, CHART_WIDTH_IN_PIXELS);
int panel_x = chart_width - HIT_SLTP_PANEL_WIDTH - 20;
if (panel_x < 10)
panel_x = 10;
const int panel_y = 25;
if (!m_panel.Create(0, HIT_SLTP_PANEL_NAME, 0, panel_x, panel_y,
panel_x + HIT_SLTP_PANEL_WIDTH + 8,
panel_y + HIT_SLTP_PANEL_HEIGHT))
{
Print("SLTP panel create failed: err=", GetLastError());
return false;
}
CreateLabel(m_label_title, "HIT_SLTP_LABEL_TITLE", HIT_SLTP_LABEL_X, HIT_SLTP_TITLE_Y,
HIT_SLTP_TITLE_WIDTH, "HIT SLTP Manager");
CreateLabel(m_label_master, "HIT_SLTP_LABEL_MASTER", HIT_SLTP_LABEL_X, HIT_SLTP_MASTER_ROW_Y,
HIT_SLTP_LABEL_WIDTH, "Manager");
CreateButton(m_button_master, HIT_SLTP_MASTER_BTN_NAME, HIT_SLTP_BUTTON_X, HIT_SLTP_MASTER_ROW_Y,
HIT_SLTP_BUTTON_WIDTH, HIT_SLTP_BUTTON_HEIGHT);
CreateLabel(m_label_breakeven, "HIT_SLTP_LABEL_BE", HIT_SLTP_LABEL_X, HIT_SLTP_BE_ROW_Y,
HIT_SLTP_LABEL_WIDTH, "BreakEven");
CreateButton(m_button_breakeven, HIT_SLTP_BE_BTN_NAME, HIT_SLTP_BUTTON_X, HIT_SLTP_BE_ROW_Y,
HIT_SLTP_BUTTON_WIDTH, HIT_SLTP_BUTTON_HEIGHT);
CreateLabel(m_label_be_trigger, "HIT_SLTP_LABEL_BE_TRG", HIT_SLTP_EDIT_X1,
HIT_SLTP_BE_ROW_Y - HIT_SLTP_ROW_HEIGHT, HIT_SLTP_EDIT_WIDTH, "Trigger");
CreateLabel(m_label_be_buffer, "HIT_SLTP_LABEL_BE_BUF", HIT_SLTP_EDIT_X2,
HIT_SLTP_BE_ROW_Y - HIT_SLTP_ROW_HEIGHT, HIT_SLTP_EDIT_WIDTH, "Buffer");
CreateEdit(m_edit_breakeven_trigger, HIT_SLTP_BE_TRIGGER_EDIT_NAME, HIT_SLTP_EDIT_X1,
HIT_SLTP_BE_ROW_Y, HIT_SLTP_EDIT_WIDTH);
CreateEdit(m_edit_breakeven_buffer, HIT_SLTP_BE_BUFFER_EDIT_NAME, HIT_SLTP_EDIT_X2,
HIT_SLTP_BE_ROW_Y, HIT_SLTP_EDIT_WIDTH);
CreateLabel(m_label_elapsed_breakeven, "HIT_SLTP_LABEL_ELAPSED", HIT_SLTP_LABEL_X,
HIT_SLTP_ELAPSED_ROW_Y, HIT_SLTP_LABEL_WIDTH, "Elapsed BE");
CreateButton(m_button_elapsed_breakeven, HIT_SLTP_ELAPSED_BE_BTN_NAME, HIT_SLTP_BUTTON_X,
HIT_SLTP_ELAPSED_ROW_Y, HIT_SLTP_BUTTON_WIDTH, HIT_SLTP_BUTTON_HEIGHT);
CreateLabel(m_label_elapsed_hours, "HIT_SLTP_LABEL_EL_H", HIT_SLTP_EDIT_X1,
HIT_SLTP_ELAPSED_ROW_Y - HIT_SLTP_ROW_HEIGHT, HIT_SLTP_EDIT_WIDTH, "Hours");
CreateLabel(m_label_elapsed_buffer, "HIT_SLTP_LABEL_EL_BUF", HIT_SLTP_EDIT_X2,
HIT_SLTP_ELAPSED_ROW_Y - HIT_SLTP_ROW_HEIGHT, HIT_SLTP_EDIT_WIDTH, "Buffer");
CreateEdit(m_edit_elapsed_hours, HIT_SLTP_ELAPSED_HOURS_EDIT_NAME, HIT_SLTP_EDIT_X1,
HIT_SLTP_ELAPSED_ROW_Y, HIT_SLTP_EDIT_WIDTH);
CreateEdit(m_edit_elapsed_buffer, HIT_SLTP_ELAPSED_BUFFER_EDIT_NAME, HIT_SLTP_EDIT_X2,
HIT_SLTP_ELAPSED_ROW_Y, HIT_SLTP_EDIT_WIDTH);
CreateLabel(m_label_active_trailing, "HIT_SLTP_LABEL_ACTIVE", HIT_SLTP_LABEL_X,
HIT_SLTP_ACTIVE_ROW_Y, HIT_SLTP_LABEL_WIDTH, "Active Trail");
CreateButton(m_button_active_trailing, HIT_SLTP_ACTIVE_TRAIL_BTN_NAME, HIT_SLTP_BUTTON_X,
HIT_SLTP_ACTIVE_ROW_Y, HIT_SLTP_BUTTON_WIDTH, HIT_SLTP_BUTTON_HEIGHT);
CreateLabel(m_label_active_start, "HIT_SLTP_LABEL_ACT_START", HIT_SLTP_EDIT_X1,
HIT_SLTP_ACTIVE_ROW_Y - HIT_SLTP_ROW_HEIGHT, HIT_SLTP_EDIT_WIDTH, "Start");
CreateLabel(m_label_active_offset, "HIT_SLTP_LABEL_ACT_OFFSET", HIT_SLTP_EDIT_X2,
HIT_SLTP_ACTIVE_ROW_Y - HIT_SLTP_ROW_HEIGHT, HIT_SLTP_EDIT_WIDTH, "Offset");
CreateLabel(m_label_active_step_trigger, "HIT_SLTP_LABEL_ACT_TRG", HIT_SLTP_EDIT_X3,
HIT_SLTP_ACTIVE_ROW_Y - HIT_SLTP_ROW_HEIGHT, HIT_SLTP_EDIT_WIDTH, "StepTrig");
CreateLabel(m_label_active_step_move, "HIT_SLTP_LABEL_ACT_MOVE", HIT_SLTP_EDIT_X4,
HIT_SLTP_ACTIVE_ROW_Y - HIT_SLTP_ROW_HEIGHT, HIT_SLTP_EDIT_WIDTH, "StepMove");
CreateEdit(m_edit_active_start, HIT_SLTP_ACTIVE_START_EDIT_NAME, HIT_SLTP_EDIT_X1,
HIT_SLTP_ACTIVE_ROW_Y, HIT_SLTP_EDIT_WIDTH);
CreateEdit(m_edit_active_offset, HIT_SLTP_ACTIVE_OFFSET_EDIT_NAME, HIT_SLTP_EDIT_X2,
HIT_SLTP_ACTIVE_ROW_Y, HIT_SLTP_EDIT_WIDTH);
CreateEdit(m_edit_active_step_trigger, HIT_SLTP_ACTIVE_STEP_TRIGGER_EDIT_NAME, HIT_SLTP_EDIT_X3,
HIT_SLTP_ACTIVE_ROW_Y, HIT_SLTP_EDIT_WIDTH);
CreateEdit(m_edit_active_step_move, HIT_SLTP_ACTIVE_STEP_MOVE_EDIT_NAME, HIT_SLTP_EDIT_X4,
HIT_SLTP_ACTIVE_ROW_Y, HIT_SLTP_EDIT_WIDTH);
CreateLabel(m_label_tp_progress, "HIT_SLTP_LABEL_TP_PROGRESS", HIT_SLTP_LABEL_X,
HIT_SLTP_TP_ROW_Y, HIT_SLTP_LABEL_WIDTH, "TP Progress");
CreateButton(m_button_tp_progress, HIT_SLTP_TP_PROGRESS_BTN_NAME, HIT_SLTP_BUTTON_X,
HIT_SLTP_TP_ROW_Y, HIT_SLTP_BUTTON_WIDTH, HIT_SLTP_BUTTON_HEIGHT);
CreateLabel(m_label_tp_trigger, "HIT_SLTP_LABEL_TP_TRG", HIT_SLTP_EDIT_X1,
HIT_SLTP_TP_ROW_Y - HIT_SLTP_ROW_HEIGHT, HIT_SLTP_EDIT_WIDTH, "Trig %");
CreateLabel(m_label_tp_lock, "HIT_SLTP_LABEL_TP_LOCK", HIT_SLTP_EDIT_X2,
HIT_SLTP_TP_ROW_Y - HIT_SLTP_ROW_HEIGHT, HIT_SLTP_EDIT_WIDTH, "Lock %");
CreateEdit(m_edit_tp_trigger, HIT_SLTP_TP_TRIGGER_EDIT_NAME, HIT_SLTP_EDIT_X1,
HIT_SLTP_TP_ROW_Y, HIT_SLTP_EDIT_WIDTH);
CreateEdit(m_edit_tp_lock, HIT_SLTP_TP_LOCK_EDIT_NAME, HIT_SLTP_EDIT_X2,
HIT_SLTP_TP_ROW_Y, HIT_SLTP_EDIT_WIDTH);
CreateLabel(m_label_high_volatility, "HIT_SLTP_LABEL_HIGH_VOL", HIT_SLTP_LABEL_X,
HIT_SLTP_HIGH_VOL_ROW_Y, HIT_SLTP_LABEL_WIDTH, "High Vol");
CreateButton(m_button_high_volatility, HIT_SLTP_HIGH_VOL_BTN_NAME, HIT_SLTP_BUTTON_X,
HIT_SLTP_HIGH_VOL_ROW_Y, HIT_SLTP_BUTTON_WIDTH, HIT_SLTP_BUTTON_HEIGHT);
CreateButton(m_button_apply, HIT_SLTP_APPLY_BTN_NAME, HIT_SLTP_EDIT_X4, HIT_SLTP_APPLY_ROW_Y,
HIT_SLTP_APPLY_WIDTH, HIT_SLTP_APPLY_HEIGHT);
m_button_apply.Text("APPLY");
m_button_apply.Color(clrWhite);
m_button_apply.ColorBackground(clrSeaGreen);
m_button_apply.ColorBorder(clrSeaGreen);
RefreshControls();
m_panel.Run();
return true;
}
void Destroy(const int reason)
{
m_panel.Destroy(reason);
}
void SetInitialValues()
{
RefreshControls();
}
bool HandleChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam,
SLTPManagerPanelSettings &applied_settings)
{
m_panel.ChartEvent(id, lparam, dparam, sparam);
if (id != CHARTEVENT_OBJECT_CLICK)
return false;
if (sparam == HIT_SLTP_MASTER_BTN_NAME)
{
m_settings.manager_enabled = !m_settings.manager_enabled;
RefreshButtons();
return false;
}
if (sparam == HIT_SLTP_BE_BTN_NAME)
{
m_settings.use_breakeven = !m_settings.use_breakeven;
if (m_settings.use_breakeven)
m_settings.use_active_trailing = false;
RefreshButtons();
return false;
}
if (sparam == HIT_SLTP_ELAPSED_BE_BTN_NAME)
{
m_settings.use_elapsed_breakeven = !m_settings.use_elapsed_breakeven;
RefreshButtons();
return false;
}
if (sparam == HIT_SLTP_ACTIVE_TRAIL_BTN_NAME)
{
m_settings.use_active_trailing = !m_settings.use_active_trailing;
if (m_settings.use_active_trailing)
m_settings.use_breakeven = false;
RefreshButtons();
return false;
}
if (sparam == HIT_SLTP_TP_PROGRESS_BTN_NAME)
{
m_settings.use_tp_progress_stop = !m_settings.use_tp_progress_stop;
RefreshButtons();
return false;
}
if (sparam == HIT_SLTP_HIGH_VOL_BTN_NAME)
{
m_settings.use_high_volatility_limit = !m_settings.use_high_volatility_limit;
RefreshButtons();
return false;
}
if (sparam == HIT_SLTP_APPLY_BTN_NAME)
{
if (!ReadInputs())
return false;
applied_settings = m_settings;
Print("HIT SLTP panel settings applied.");
return true;
}
return false;
}
private:
void CreateButton(CButton &button,
const string name,
const int x,
const int y,
const int width,
const int height)
{
if (!button.Create(0, name, 0, x, y, 0, 0))
{
Print("SLTP button create failed: ", name, " err=", GetLastError());
return;
}
button.Width(width);
button.Height(height);
button.Font(HIT_SLTP_FONT_STYLE);
button.FontSize(HIT_SLTP_FONT_SIZE);
m_panel.Add(button);
}
void CreateLabel(CLabel &label,
const string name,
const int x,
const int y,
const int width,
const string text)
{
if (!label.Create(0, name, 0, x, y, 0, 0))
{
Print("SLTP label create failed: ", name, " err=", GetLastError());
return;
}
label.Width(width);
label.Height(HIT_SLTP_ROW_HEIGHT);
label.Text(text);
label.Font(HIT_SLTP_FONT_STYLE);
label.FontSize(HIT_SLTP_FONT_SIZE);
label.Color(clrDimGray);
label.ColorBackground(clrDimGray);
label.ColorBorder(clrDimGray);
m_panel.Add(label);
}
void CreateEdit(CEdit &edit,
const string name,
const int x,
const int y,
const int width)
{
if (!edit.Create(0, name, 0, x, y, 0, 0))
{
Print("SLTP edit create failed: ", name, " err=", GetLastError());
return;
}
edit.Width(width);
edit.Height(HIT_SLTP_ROW_HEIGHT);
edit.Font(HIT_SLTP_FONT_STYLE);
edit.FontSize(HIT_SLTP_FONT_SIZE);
edit.Color(clrDimGray);
edit.ColorBackground(clrWhite);
edit.ColorBorder(clrDimGray);
m_panel.Add(edit);
}
void RefreshControls()
{
RefreshButtons();
m_edit_breakeven_trigger.Text(DoubleToString(m_settings.breakeven_trigger_pips, 1));
m_edit_breakeven_buffer.Text(DoubleToString(m_settings.breakeven_buffer_pips, 1));
m_edit_elapsed_hours.Text(DoubleToString(m_settings.elapsed_breakeven_hours, 1));
m_edit_elapsed_buffer.Text(DoubleToString(m_settings.elapsed_breakeven_buffer_pips, 1));
m_edit_active_start.Text(DoubleToString(m_settings.active_breakeven_pips, 1));
m_edit_active_offset.Text(DoubleToString(m_settings.active_stop_loss_offset_pips, 1));
m_edit_active_step_trigger.Text(DoubleToString(m_settings.active_step_trigger_pips, 1));
m_edit_active_step_move.Text(DoubleToString(m_settings.active_step_move_pips, 1));
m_edit_tp_trigger.Text(DoubleToString(m_settings.tp_progress_trigger_percent, 1));
m_edit_tp_lock.Text(DoubleToString(m_settings.tp_progress_sl_lock_percent, 1));
}
void RefreshButtons()
{
ApplyToggleButton(m_button_master, m_settings.manager_enabled, "ON", "OFF");
ApplyToggleButton(m_button_breakeven, m_settings.use_breakeven, "ON", "OFF");
ApplyToggleButton(m_button_elapsed_breakeven, m_settings.use_elapsed_breakeven, "ON", "OFF");
ApplyToggleButton(m_button_active_trailing, m_settings.use_active_trailing, "ON", "OFF");
ApplyToggleButton(m_button_tp_progress, m_settings.use_tp_progress_stop, "ON", "OFF");
ApplyToggleButton(m_button_high_volatility, m_settings.use_high_volatility_limit, "ON", "OFF");
}
void ApplyToggleButton(CButton &button,
const bool enabled,
const string on_text,
const string off_text)
{
if (enabled)
{
button.Text(on_text);
button.Color(clrWhite);
button.ColorBackground(clrRoyalBlue);
button.ColorBorder(clrRoyalBlue);
}
else
{
button.Text(off_text);
button.Color(clrRoyalBlue);
button.ColorBackground(clrWhite);
button.ColorBorder(clrRoyalBlue);
}
}
bool ReadInputs()
{
bool ok = true;
ok = ReadDoubleValue(m_edit_breakeven_trigger, "BreakEven Trigger", 0.0, 10000.0,
m_settings.breakeven_trigger_pips, m_settings.breakeven_trigger_pips) && ok;
ok = ReadDoubleValue(m_edit_breakeven_buffer, "BreakEven Buffer", 0.0, 10000.0,
m_settings.breakeven_buffer_pips, m_settings.breakeven_buffer_pips) && ok;
ok = ReadDoubleValue(m_edit_elapsed_hours, "Elapsed BE Hours", 0.0, 10000.0,
m_settings.elapsed_breakeven_hours, m_settings.elapsed_breakeven_hours) && ok;
ok = ReadDoubleValue(m_edit_elapsed_buffer, "Elapsed BE Buffer", 0.0, 10000.0,
m_settings.elapsed_breakeven_buffer_pips, m_settings.elapsed_breakeven_buffer_pips) && ok;
ok = ReadDoubleValue(m_edit_active_start, "Active Trail Start", 0.0, 10000.0,
m_settings.active_breakeven_pips, m_settings.active_breakeven_pips) && ok;
ok = ReadDoubleValue(m_edit_active_offset, "Active Trail Offset", 0.0, 10000.0,
m_settings.active_stop_loss_offset_pips, m_settings.active_stop_loss_offset_pips) && ok;
ok = ReadDoubleValue(m_edit_active_step_trigger, "Active Trail Step Trigger", 0.1, 10000.0,
m_settings.active_step_trigger_pips, m_settings.active_step_trigger_pips) && ok;
ok = ReadDoubleValue(m_edit_active_step_move, "Active Trail Step Move", 0.1, 10000.0,
m_settings.active_step_move_pips, m_settings.active_step_move_pips) && ok;
ok = ReadDoubleValue(m_edit_tp_trigger, "TP Progress Trigger", 0.1, 100.0,
m_settings.tp_progress_trigger_percent, m_settings.tp_progress_trigger_percent) && ok;
ok = ReadDoubleValue(m_edit_tp_lock, "TP Progress Lock", 0.0, 100.0,
m_settings.tp_progress_sl_lock_percent, m_settings.tp_progress_sl_lock_percent) && ok;
if (m_settings.use_breakeven && m_settings.use_active_trailing)
{
MessageBox("BreakEven and Active Trail cannot both be enabled.", "SLTP panel error", MB_ICONERROR);
m_settings.use_active_trailing = false;
RefreshButtons();
ok = false;
}
if (!ok)
RefreshControls();
return ok;
}
bool ReadDoubleValue(CEdit &edit,
const string label,
const double min_value,
const double max_value,
const double default_value,
double &target)
{
const string text = edit.Text();
if (!IsNumericText(text))
{
ShowValueError(edit, label, min_value, max_value, default_value, target);
return false;
}
const double value = StringToDouble(text);
if (value < min_value || value > max_value)
{
ShowValueError(edit, label, min_value, max_value, default_value, target);
return false;
}
target = value;
return true;
}
void ShowValueError(CEdit &edit,
const string label,
const double min_value,
const double max_value,
const double default_value,
double &target)
{
MessageBox(label + " must be between " + DoubleToString(min_value, 1) +
" and " + DoubleToString(max_value, 1) + ".",
"SLTP panel error",
MB_ICONERROR);
edit.Text(DoubleToString(default_value, 1));
target = default_value;
}
bool IsNumericText(const string text)
{
bool has_digit = false;
bool has_dot = false;
bool seen_value_char = false;
const int length = StringLen(text);
for (int i = 0; i < length; ++i)
{
const ushort ch = StringGetCharacter(text, i);
if (ch == 32 || ch == 9)
continue;
if (ch >= 48 && ch <= 57)
{
has_digit = true;
seen_value_char = true;
continue;
}
if (ch == 46 && !has_dot)
{
has_dot = true;
seen_value_char = true;
continue;
}
if ((ch == 43 || ch == 45) && !seen_value_char)
{
seen_value_char = true;
continue;
}
return false;
}
return has_digit;
}
};
#endif
+546
View File
@@ -0,0 +1,546 @@
#ifndef TRADING_PANEL_PANEL_MQH
#define TRADING_PANEL_PANEL_MQH
#include <Controls/Dialog.mqh>
#include <Controls/Button.mqh>
#include <Controls/Edit.mqh>
#include <Controls/Label.mqh>
#define PANEL_NAME "SettingPanel"
#define PANEL_WIDTH 420
#define PANEL_HIEIGHT 260
#define ROW_HEIGHT 18
#define LBL_X 15
#define EDIT_X 105
#define BTN_X 160
#define FONT_SIZE 9
#define FONT_STYLE "Arial Black"
#define HEIKIN_BTN_NAME "Use_Heikin BTN"
#define LIMIT_BTN_NAME "Time_Limit_Close BTN"
#define INPUT_LOCK_BTN_NAME "INPUT_LOCK BTN"
#define BUY_TP_PLUS_BTN_NAME "Buy_TP_Plus BTN"
#define BUY_TP_MINUS_BTN_NAME "Buy_TP_Minus BTN"
#define SELL_TP_PLUS_BTN_NAME "Sell_TP_Plus BTN"
#define SELL_TP_MINUS_BTN_NAME "Sell_TP_Minus BTN"
#define BUY_TOTAL_BE_BTN_NAME "BuyTotal_BE BTN"
#define SELL_TOTAL_BE_BTN_NAME "SellTotal_BE BTN"
#define EDIT_EI_NAME "ExitTimeInterval"
#define EDIT_RANGE_NAME "RangePips"
#define EDIT_BREAKEVEN_NAME "BreakEven"
#define EDIT_BREAKEVEN_INIT_NAME "BreakEvenInit"
#define EDIT_STEP_TRAIL_NAME "StepTrail"
#define EDIT_STEP_MOVE_NAME "StepMove"
#define EDIT_SL_NAME "StopLoss"
#define EDIT_TP_NAME "TakeProfit"
#define EDIT_BUY_PLUS_NAME "Buy_TP"
#define EDIT_SELL_TP_PLUS_NAME "Sell_TP"
#define EDIT_SL_OFFSET_NAME "StopLossOffset"
class CTradingPanelPanel
{
private:
CAppDialog m_panel;
CEdit m_input_1st;
CEdit m_input_2nd;
CEdit m_input_3rd;
CEdit m_input_4th;
CEdit m_input_5th;
CEdit m_input_6th;
CEdit m_input_7th;
CEdit m_input_8th;
CEdit m_input_9th;
CEdit m_input_10th;
CEdit m_input_11th;
CButton m_button_timelimit_exit;
CButton m_button_input_lock;
CButton m_button_buy_tp_plus;
CButton m_button_buy_tp_minus;
CButton m_button_sell_tp_plus;
CButton m_button_sell_tp_minus;
CButton m_button_buy_total_be;
CButton m_button_sell_total_be;
CLabel m_infoLabel_1st;
CLabel m_infoLabel_2nd;
CLabel m_infoLabel_3rd;
CLabel m_infoLabel_4th;
CLabel m_infoLabel_5th;
CLabel m_infoLabel_6th;
CLabel m_infoLabel_7th;
CLabel m_infoLabel_9th;
CLabel m_infoLabel_10th;
CLabel m_infoLabel_11th;
CLabel m_infoLabel_12th;
CLabel m_infoLabel_13th;
CLabel m_infoLabel_14th;
CLabel m_infoLabel_15th;
CLabel m_infoLabel_16th;
int m_exitTimeIntervalInSeconds;
double m_range_pips;
double m_breakeven_pips;
double m_stop_loss_offset_pips;
double m_step_trigger_pips;
double m_step_move_pips;
double m_default_sl_pips;
double m_take_profit_pips;
double m_buy_tp_pips;
double m_sell_tp_pips;
double m_stop_offset_pips;
public:
void Init(const int initial_exit_time_interval_hours,
const double initial_range_pips,
const double initial_breakeven_pips,
const double initial_stop_loss_offset_pips,
const double initial_step_trigger_pips,
const double initial_step_move_pips,
const double initial_default_sl_pips,
const double initial_take_profit_pips,
const double initial_tp_edit_pips,
const double initial_stop_offset_pips)
{
m_exitTimeIntervalInSeconds = initial_exit_time_interval_hours * 3600;
m_range_pips = initial_range_pips;
m_breakeven_pips = initial_breakeven_pips;
m_stop_loss_offset_pips = initial_stop_loss_offset_pips;
m_step_trigger_pips = initial_step_trigger_pips;
m_step_move_pips = initial_step_move_pips;
m_default_sl_pips = initial_default_sl_pips;
m_take_profit_pips = initial_take_profit_pips;
m_buy_tp_pips = initial_tp_edit_pips;
m_sell_tp_pips = initial_tp_edit_pips;
m_stop_offset_pips = initial_stop_offset_pips;
}
bool CreatePanel(const bool is_input_locked)
{
const int chart_height = (int)ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS);
const int panel_x = 10;
const int panel_y = chart_height - PANEL_HIEIGHT - 10;
if (!m_panel.Create(0, PANEL_NAME, 0, panel_x, panel_y,
panel_x + PANEL_WIDTH + 8, panel_y + PANEL_HIEIGHT))
{
Print("Panel create failed: err=", GetLastError());
return false;
}
CreateButton(m_button_timelimit_exit, LIMIT_BTN_NAME, BTN_X, 150, 80, ROW_HEIGHT + 5,
"ON", clrRoyalBlue, clrWhite);
CreateButton(m_button_input_lock, INPUT_LOCK_BTN_NAME, BTN_X, 195, 80, ROW_HEIGHT + 5,
"UNLOCK", clrRoyalBlue, clrWhite);
CreateButton(m_button_buy_tp_plus, BUY_TP_PLUS_BTN_NAME, BTN_X + 193, 20, 22, ROW_HEIGHT,
"▲", clrGreen, clrWhite);
CreateButton(m_button_buy_tp_minus, BUY_TP_MINUS_BTN_NAME, BTN_X + 219, 20, 22, ROW_HEIGHT,
"▼", clrRed, clrWhite);
CreateButton(m_button_sell_tp_plus, SELL_TP_PLUS_BTN_NAME, BTN_X + 193, 45, 22, ROW_HEIGHT,
"▼", clrGreen, clrWhite);
CreateButton(m_button_sell_tp_minus, SELL_TP_MINUS_BTN_NAME, BTN_X + 219, 45, 22, ROW_HEIGHT,
"▲", clrRed, clrWhite);
CreateButton(m_button_buy_total_be, BUY_TOTAL_BE_BTN_NAME, BTN_X + 100, 105, 60, ROW_HEIGHT + 5,
"OFF", clrWhite, clrRoyalBlue);
CreateButton(m_button_sell_total_be, SELL_TOTAL_BE_BTN_NAME, BTN_X + 180, 105, 60, ROW_HEIGHT + 5,
"OFF", clrWhite, clrRoyalBlue);
CreateLabel(m_infoLabel_1st, "label_1", LBL_X, 20, "ExitTime(h)");
CreateLabel(m_infoLabel_2nd, "label_2", LBL_X, 42, "Range");
CreateLabel(m_infoLabel_3rd, "label_3", LBL_X, 64, "BreakEven");
CreateLabel(m_infoLabel_4th, "label_4", LBL_X, 109, "TrailStep");
CreateLabel(m_infoLabel_5th, "label_5", LBL_X, 131, "StepMove");
CreateLabel(m_infoLabel_6th, "label_6", LBL_X, 153, "StopLoss");
CreateLabel(m_infoLabel_7th, "label_7", LBL_X, 175, "TakeProfit");
CreateLabel(m_infoLabel_9th, "label_9", BTN_X + 4, 130, "EXIT_TIME");
CreateLabel(m_infoLabel_10th, "label_10", BTN_X + 10, 175, "SETTING");
CreateLabel(m_infoLabel_11th, "label_11", BTN_X + 100, 20, "Buy TP");
CreateLabel(m_infoLabel_12th, "label_12", BTN_X + 100, 45, "Sell TP");
CreateLabel(m_infoLabel_13th, "label_13", BTN_X + 95, 85, "AllBuy_BE");
CreateLabel(m_infoLabel_14th, "label_14", BTN_X + 175, 85, "AllSell_BE");
CreateLabel(m_infoLabel_15th, "label_19", LBL_X, 87, "BE_Offset");
CreateLabel(m_infoLabel_16th, "label_22", LBL_X, 197, "StopOffset");
CreateEdit(m_input_1st, EDIT_EI_NAME, EDIT_X, 20);
CreateEdit(m_input_2nd, EDIT_RANGE_NAME, EDIT_X, 42);
CreateEdit(m_input_3rd, EDIT_BREAKEVEN_NAME, EDIT_X, 64);
CreateEdit(m_input_10th, EDIT_BREAKEVEN_INIT_NAME, EDIT_X, 86);
CreateEdit(m_input_4th, EDIT_STEP_TRAIL_NAME, EDIT_X, 108);
CreateEdit(m_input_5th, EDIT_STEP_MOVE_NAME, EDIT_X, 130);
CreateEdit(m_input_6th, EDIT_SL_NAME, EDIT_X, 152);
CreateEdit(m_input_7th, EDIT_TP_NAME, EDIT_X, 174);
CreateEdit(m_input_8th, EDIT_BUY_PLUS_NAME, BTN_X + 151, 20);
CreateEdit(m_input_9th, EDIT_SELL_TP_PLUS_NAME, BTN_X + 151, 45);
CreateEdit(m_input_11th, EDIT_SL_OFFSET_NAME, EDIT_X, 196);
SetReadOnly(is_input_locked);
m_panel.Run();
return true;
}
void Destroy(const int reason)
{
m_panel.Destroy(reason);
}
void SetInitialValues()
{
m_input_1st.Text(IntegerToString(m_exitTimeIntervalInSeconds / 3600));
m_input_2nd.Text(DoubleToString(m_range_pips, 0));
m_input_3rd.Text(DoubleToString(m_breakeven_pips, 0));
m_input_4th.Text(DoubleToString(m_step_trigger_pips, 0));
m_input_5th.Text(DoubleToString(m_step_move_pips, 0));
m_input_6th.Text(DoubleToString(m_default_sl_pips, 0));
m_input_7th.Text(DoubleToString(m_take_profit_pips, 0));
m_input_8th.Text(DoubleToString(m_buy_tp_pips, 0));
m_input_9th.Text(DoubleToString(m_sell_tp_pips, 0));
m_input_10th.Text(DoubleToString(m_stop_loss_offset_pips, 0));
m_input_11th.Text(DoubleToString(m_stop_offset_pips, 0));
}
bool HandleChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam,
const int default_exit_time_interval_hours,
const double default_range_pips,
const double default_breakeven_pips,
const double default_stop_loss_offset_pips,
const double default_step_trigger_pips,
const double default_step_move_pips,
const double default_sl_pips,
const double default_take_profit_pips,
const double default_tp_edit_pips,
const double default_stop_offset_pips,
bool &io_timelimit_exit,
bool &io_input_lock,
bool &io_buy_total_be_flg,
bool &io_sell_total_be_flg,
int &active_exit_seconds,
double &active_breakeven_pips,
double &active_stop_loss_offset_pips,
double &active_step_trigger_pips,
double &active_step_move_pips,
double &active_default_sl_pips,
double &active_take_profit_pips,
double &active_stop_offset_pips,
ENUM_POSITION_TYPE &tp_side,
double &tp_adjust_pips)
{
tp_side = (ENUM_POSITION_TYPE)-1;
tp_adjust_pips = 0.0;
UpdateInputValues(default_exit_time_interval_hours,
default_range_pips,
default_breakeven_pips,
default_stop_loss_offset_pips,
default_step_trigger_pips,
default_step_move_pips,
default_sl_pips,
default_take_profit_pips,
default_tp_edit_pips,
default_stop_offset_pips);
m_panel.ChartEvent(id, lparam, dparam, sparam);
if (id != CHARTEVENT_OBJECT_CLICK)
return false;
if (sparam == LIMIT_BTN_NAME)
{
io_timelimit_exit = !io_timelimit_exit;
ApplyToggleButton(m_button_timelimit_exit, io_timelimit_exit, "ON", "OFF");
Print("TimeExit: ", io_timelimit_exit ? "ON" : "OFF");
return false;
}
if (sparam == INPUT_LOCK_BTN_NAME)
{
io_input_lock = !io_input_lock;
SetReadOnly(io_input_lock);
if (io_input_lock)
{
m_button_input_lock.Text("UNLOCK");
m_button_input_lock.Color(clrWhite);
m_button_input_lock.ColorBackground(clrRoyalBlue);
m_button_input_lock.ColorBorder(clrRoyalBlue);
Print("button_input_lock: パネルのインプット:ロック");
active_exit_seconds = m_exitTimeIntervalInSeconds;
active_breakeven_pips = m_breakeven_pips;
active_stop_loss_offset_pips = m_stop_loss_offset_pips;
active_step_trigger_pips = m_step_trigger_pips;
active_step_move_pips = m_step_move_pips;
active_take_profit_pips = m_take_profit_pips;
active_default_sl_pips = m_default_sl_pips;
active_stop_offset_pips = m_stop_offset_pips;
Print("--------------------------------------------------------");
Print("時間制限クローズ(時間): ", active_exit_seconds / 3600, "\n",
"ブレークイーブン(pips): ", active_breakeven_pips, "\n",
"ブレークイーブン建値(pips): ", active_stop_loss_offset_pips, "\n",
"トレール更新(pips): ", active_step_trigger_pips, "\n",
"トレール更新幅(pips): ", active_step_move_pips, "\n",
"ストップロス(pips): ", active_default_sl_pips, "\n",
"テイクプロフィット(pips): ", active_take_profit_pips, "\n",
"ストップロスオフセット(pips): ", active_stop_offset_pips);
Print("--------------------------------------------------------");
Print("EA設定変更");
}
else
{
m_button_input_lock.Text("LOCK");
m_button_input_lock.Color(clrRoyalBlue);
m_button_input_lock.ColorBackground(clrWhite);
m_button_input_lock.ColorBorder(clrRoyalBlue);
Print("button_input_lock: パネルのインプット:ロック解除");
}
return false;
}
if (sparam == BUY_TP_PLUS_BTN_NAME)
{
Print("Buy_TP Plus PRESSED ", m_buy_tp_pips, " pips");
tp_side = POSITION_TYPE_BUY;
tp_adjust_pips = +m_buy_tp_pips;
return true;
}
if (sparam == BUY_TP_MINUS_BTN_NAME)
{
Print("Buy_TP Minus PRESSED ", m_buy_tp_pips, " pips");
tp_side = POSITION_TYPE_BUY;
tp_adjust_pips = -m_buy_tp_pips;
return true;
}
if (sparam == SELL_TP_PLUS_BTN_NAME)
{
Print("Sell_TP Plus PRESSED ", m_sell_tp_pips, " pips");
tp_side = POSITION_TYPE_SELL;
tp_adjust_pips = +m_sell_tp_pips;
return true;
}
if (sparam == SELL_TP_MINUS_BTN_NAME)
{
Print("Sell_TP Minus PRESSED ", m_sell_tp_pips, " pips");
tp_side = POSITION_TYPE_SELL;
tp_adjust_pips = -m_sell_tp_pips;
return true;
}
if (sparam == BUY_TOTAL_BE_BTN_NAME)
{
io_buy_total_be_flg = !io_buy_total_be_flg;
ApplyToggleButton(m_button_buy_total_be, io_buy_total_be_flg, "ON", "OFF");
Print("Buy_Total_BE: ", io_buy_total_be_flg ? "ON" : "OFF");
return false;
}
if (sparam == SELL_TOTAL_BE_BTN_NAME)
{
io_sell_total_be_flg = !io_sell_total_be_flg;
ApplyToggleButton(m_button_sell_total_be, io_sell_total_be_flg, "ON", "OFF");
Print("Sell_Total_BE: ", io_sell_total_be_flg ? "ON" : "OFF");
return false;
}
return false;
}
private:
void CreateButton(CButton &button,
const string name,
const int x,
const int y,
const int width,
const int height,
const string text,
const color bg_color,
const color text_color)
{
if (!button.Create(0, name, 0, x, y, 0, 0))
{
Print("Button create failed: ", name, " err=", GetLastError());
return;
}
button.Width(width);
button.Height(height);
button.ColorBackground(bg_color);
button.ColorBorder(text_color == clrRoyalBlue ? clrRoyalBlue : bg_color);
button.Text(text);
button.Color(text_color);
button.Font(FONT_STYLE);
button.FontSize(FONT_SIZE);
m_panel.Add(button);
}
void CreateLabel(CLabel &label,
const string name,
const int x,
const int y,
const string text)
{
if (!label.Create(0, name, 0, x, y, 0, 0))
{
Print("Label create failed: ", name, " err=", GetLastError());
return;
}
label.Width(0);
label.Height(ROW_HEIGHT);
label.Text(text);
label.Font(FONT_STYLE);
label.FontSize(FONT_SIZE);
label.ColorBackground(clrDimGray);
label.Color(clrDimGray);
label.ColorBorder(clrDimGray);
m_panel.Add(label);
}
void CreateEdit(CEdit &edit,
const string name,
const int x,
const int y)
{
if (!edit.Create(0, name, 0, x, y, 0, 0))
{
Print("Edit create failed: ", name, " err=", GetLastError());
return;
}
edit.Width(37);
edit.Height(ROW_HEIGHT);
edit.Text("");
edit.Font(FONT_STYLE);
edit.FontSize(FONT_SIZE);
edit.ColorBackground(clrWhite);
edit.Color(clrDimGray);
edit.ColorBorder(clrDimGray);
m_panel.Add(edit);
}
void SetReadOnly(const bool is_input_locked)
{
m_input_1st.ReadOnly(is_input_locked);
m_input_2nd.ReadOnly(is_input_locked);
m_input_3rd.ReadOnly(is_input_locked);
m_input_4th.ReadOnly(is_input_locked);
m_input_5th.ReadOnly(is_input_locked);
m_input_6th.ReadOnly(is_input_locked);
m_input_7th.ReadOnly(is_input_locked);
m_input_8th.ReadOnly(is_input_locked);
m_input_9th.ReadOnly(is_input_locked);
m_input_10th.ReadOnly(is_input_locked);
m_input_11th.ReadOnly(is_input_locked);
}
void ApplyToggleButton(CButton &button,
const bool enabled,
const string on_text,
const string off_text)
{
if (enabled)
{
button.Text(on_text);
button.Color(clrWhite);
button.ColorBackground(clrRoyalBlue);
button.ColorBorder(clrRoyalBlue);
}
else
{
button.Text(off_text);
button.Color(clrRoyalBlue);
button.ColorBackground(clrWhite);
button.ColorBorder(clrRoyalBlue);
}
}
void UpdateInputValues(const int default_exit_time_interval_hours,
const double default_range_pips,
const double default_breakeven_pips,
const double default_stop_loss_offset_pips,
const double default_step_trigger_pips,
const double default_step_move_pips,
const double default_sl_pips,
const double default_take_profit_pips,
const double default_tp_edit_pips,
const double default_stop_offset_pips)
{
UpdateIntAsHours(m_input_1st, "ExitTimeIntervalは1〜240時間の範囲で入力してください",
1, 240, default_exit_time_interval_hours,
m_exitTimeIntervalInSeconds);
UpdateIntValue(m_input_2nd, "Rangeは10〜300の範囲で入力してください",
10, 300, default_range_pips, m_range_pips);
UpdateIntValue(m_input_3rd, "BreakEvenは20〜200の範囲で入力してください",
10, 200, default_breakeven_pips, m_breakeven_pips);
const int be_offset = (int)StringToInteger(m_input_10th.Text());
if (be_offset >= 0 && be_offset <= 200 && be_offset <= m_breakeven_pips)
m_stop_loss_offset_pips = be_offset;
else
{
MessageBox("BreakEvenOffsetは0〜200の範囲かつ、BreakEven以下の範囲で入力してください", "エラー", MB_ICONERROR);
m_input_10th.Text(DoubleToString(default_stop_loss_offset_pips, 0));
m_stop_loss_offset_pips = default_stop_loss_offset_pips;
}
UpdateIntValue(m_input_4th, "StepTrigerは2〜100の範囲で入力してください",
2, 100, default_step_trigger_pips, m_step_trigger_pips);
UpdateIntValue(m_input_5th, "StepMoveは1〜50の範囲で入力してください",
1, 50, default_step_move_pips, m_step_move_pips);
UpdateIntValue(m_input_6th, "StopLossは0〜999の範囲で入力してください",
0, 999, default_sl_pips, m_default_sl_pips);
UpdateIntValue(m_input_7th, "TakeProfitは0〜999の範囲で入力してください",
0, 999, default_take_profit_pips, m_take_profit_pips);
UpdateIntValue(m_input_11th, "StopLossOffsetは0〜50の範囲で入力してください",
0, 50, default_stop_offset_pips, m_stop_offset_pips);
UpdateIntValue(m_input_8th, "TakeProfitは0〜999の範囲で入力してください",
0, 999, default_tp_edit_pips, m_buy_tp_pips);
UpdateIntValue(m_input_9th, "TakeProfitは0〜999の範囲で入力してください",
0, 999, default_tp_edit_pips, m_sell_tp_pips);
}
void UpdateIntAsHours(CEdit &edit,
const string error_message,
const int min_value,
const int max_value,
const int default_hours,
int &target_seconds)
{
const int value = (int)StringToInteger(edit.Text());
if (value >= min_value && value <= max_value)
{
target_seconds = value * 3600;
return;
}
MessageBox(error_message, "エラー", MB_ICONERROR);
edit.Text(IntegerToString(default_hours));
target_seconds = default_hours * 3600;
}
void UpdateIntValue(CEdit &edit,
const string error_message,
const int min_value,
const int max_value,
const double default_value,
double &target)
{
const int value = (int)StringToInteger(edit.Text());
if (value >= min_value && value <= max_value)
{
target = value;
return;
}
MessageBox(error_message, "エラー", MB_ICONERROR);
edit.Text(DoubleToString(default_value, 0));
target = default_value;
}
};
#endif