678 lines
26 KiB
MQL5
678 lines
26 KiB
MQL5
//+------------------------------------------------------------------+
| |||
//| HKL_tool_clean.mq5 |
| |||
//| Copyright 2025, MetaQuotes Ltd. |
| |||
//| https://www.mql5.com |
| |||
//+------------------------------------------------------------------+
| |||
#property copyright "Copyright 2025, MetaQuotes Ltd."
| |||
#property link "https://www.mql5.com"
| |||
#property version "1.00"
| |||
//+------------------------------------------------------------------+
| |||
//| Expert initialization function |
| |||
//+------------------------------------------------------------------+
| |||
// --- MQL5 Libraries ---
| |||
#include <Trade\Trade.mqh>
| |||
#include <Controls/Dialog.mqh>
| |||
#include <Controls\Button.mqh>
| |||
#include <Controls\Label.mqh>
| |||
#include <Controls\ComboBox.mqh>
| |||
#include <Controls\Edit.mqh>
| |||
| |||
| |||
input int HA_PERIOD = 150; // H_Ashi period
| |||
input ulong magicnumber = 1245403; // magic number
| |||
| |||
// --- Global Objects ---
| |||
CTrade Trade; // Trade object for sending orders
| |||
MqlRates rates[] ;
| |||
double bid, ask, spread ;
| |||
int barsTotal = 0 ;
| |||
datetime current_time ;
| |||
| |||
// --- ENUMS for Panel State ---
| |||
| |||
// 1. Trade Direction
| |||
enum ENUM_DIRECTION {
| |||
DIR_BUY = ORDER_TYPE_BUY,
| |||
DIR_SELL = ORDER_TYPE_SELL,
| |||
DIR_BOTH = 2 // Option to use leapfrog mechanic
| |||
};
| |||
| |||
// 2. Entry Conditions (Simplified interpretation of "KEY" conditions)
| |||
enum ENUM_ENTRY_MODE{
| |||
| |||
MODE_HA_BLUE_ONLY = 0, // Heiken-Ashi Blue
| |||
MODE_HA_RED_ONLY = 1, // Heiken-Ashi Red
| |||
MODE_HA_BLUE_CONFIRM = 2, // HK_BUY
| |||
MODE_HA_RED_CONFIRM = 3, // HK_Sell
| |||
MODE_NEXT_BUY_KEY = 4, // next Buy Key
| |||
MODE_NEXT_SELL_KEY = 5, // next Sell Key
| |||
MODE_HKL = 6, // HKL
| |||
};
| |||
| |||
// --- GLOBAL STATE VARIABLES (Managed by Panel) ---
| |||
bool m_is_active = true;
| |||
ENUM_DIRECTION m_direction = DIR_BUY;
| |||
ENUM_ENTRY_MODE m_entry_mode = 2;
| |||
double m_risk_dollars = 100;
| |||
double m_max_sl_points = 1000.0; // 100 points = 10 pips in 5-digit brokers
| |||
double m_min_sl_points = 500;
| |||
double sl_buffer = 50; // ** change to snap
| |||
double R2r = 4;
| |||
int m_trials = 1 ;
| |||
| |||
// --- Indicator Handles and Buffers ---
| |||
int H_ashi_handle, buyKey_handle, sellKey_handle ;
| |||
double buyKey_buffer[] ,sellKey_buffer[], H_ashi_clr[] ;
| |||
| |||
| |||
// -------------Stop & Size Tracker vars ----------------
| |||
double sl_ , tp_ , lot_;
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| EA Initialization Function |
| |||
//+------------------------------------------------------------------+
| |||
int OnInit(){
| |||
// --- 1. Initialize Trade Object ---
| |||
Trade.SetExpertMagicNumber(magicnumber); // Unique magic number
| |||
Trade.SetAsyncMode(true);
| |||
Trade.SetDeviationInPoints(100);
| |||
| |||
| |||
ArraySetAsSeries(rates , true);
| |||
ArraySetAsSeries(H_ashi_clr , true);
| |||
ArraySetAsSeries(buyKey_buffer ,true);
| |||
ArraySetAsSeries(sellKey_buffer, true);
| |||
| |||
// --- 2. Initialize Indicators ---
| |||
| |||
| |||
H_ashi_handle = iCustom(NULL, 0, "My Indicators\\H_ashi_smoothed", HA_PERIOD);
| |||
buyKey_handle = sellKey_handle = ChartIndicatorGet(0,0,"Key Reversal (2 bars trend)"); //// lets try again with iCustom later
| |||
| |||
| |||
if (H_ashi_handle == INVALID_HANDLE){
| |||
Alert("ERROR: Failed to get Smoothed Heiken Ashi indicator handle. Check if 'My Indicators\\H_ashi_smoothed.ex5' exists.");
| |||
return INIT_FAILED;
| |||
}
| |||
| |||
| |||
// --- 3. Create GUI Panel ---
| |||
if(!LOAD_GUI()){
| |||
Alert("ERROR: Failed to create GUI panel.");
| |||
return INIT_FAILED;
| |||
}
| |||
//
| |||
// // --- 4. Initial Status Update ---
| |||
// UpdateStatusLabel();
| |||
| |||
return(INIT_SUCCEEDED);
| |||
}
| |||
| |||
| |||
| |||
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Expert Tick Function |
| |||
//+------------------------------------------------------------------+
| |||
void OnTick(){
| |||
| |||
current_time = TimeCurrent();
| |||
bid = SymbolInfoDouble(_Symbol,SYMBOL_BID);
| |||
ask = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
| |||
spread= ask-bid;
| |||
| |||
CopyRates(_Symbol, PERIOD_CURRENT,1,2, rates); // cheking every tick noot every bar
| |||
| |||
// Check for new bar
| |||
int bars = iBars(_Symbol,PERIOD_CURRENT);
| |||
if(barsTotal != bars){
| |||
| |||
| |||
CopyBuffer(H_ashi_handle,4,0,3,H_ashi_clr);
| |||
CopyBuffer(buyKey_handle,1,0,2,buyKey_buffer);// sell
| |||
CopyBuffer(sellKey_handle,0,0,2,sellKey_buffer);// buy
| |||
//SIGNAL();
| |||
TRADE_EXECUTIONS();
| |||
| |||
| |||
barsTotal = bars;
| |||
}
| |||
| |||
// Trackers
| |||
// Trade manager
| |||
| |||
| |||
if (!m_is_active) return;
| |||
// Execution
| |||
| |||
}
| |||
| |||
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |||
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |||
//|//////////// ////// ////// ///////////////// SIGNALS /////// ///////////////// ///////////////////////|
| |||
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |||
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |||
| |||
bool BUY_TREND(){
| |||
return (H_ashi_clr[0] == 1.0);
| |||
}
| |||
| |||
bool SELL_TREND(){
| |||
return (H_ashi_clr[0] == 2.0 );
| |||
}
| |||
| |||
bool BUY_Key(){ // Keys show a very large number if empty and the price if present
| |||
//Print( "Buy key :: " , buyKey_buffer[1] );
| |||
return (buyKey_buffer[1] < 1.797693e300 ) ; // default key numver is 1.797....e+308
| |||
}
| |||
| |||
bool SELL_Key(){
| |||
return (sellKey_buffer[1] < 1.797693e300 ) ;
| |||
}
| |||
| |||
bool SIGNAL(){
| |||
switch(m_entry_mode){
| |||
case 0:
| |||
return BUY_TREND();
| |||
case 1:
| |||
return SELL_TREND();
| |||
case 2:
| |||
return (BUY_TREND() && BUY_Key()) ;
| |||
case 3:
| |||
return (SELL_TREND() && SELL_Key()) ;
| |||
case 4:
| |||
return BUY_Key() ;
| |||
case 5:
| |||
return SELL_Key() ;
| |||
case 6:
| |||
return (BUY_TREND() && BUY_Key()) || (SELL_TREND() && SELL_Key());
| |||
default:
| |||
return false;
| |||
}
| |||
}
| |||
| |||
void TRADE_EXECUTIONS(){
| |||
| |||
//Print("Signall :::::: " , SIGNAL());
| |||
//Print("Keys :::::: " , BUY_Key());
| |||
//Print("H_Ashi :::::: " , BUY_TREND());
| |||
if ( ! (SIGNAL() && m_is_active ) ) return;
| |||
Enter_Pos();
| |||
| |||
}
| |||
| |||
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |||
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |||
//|//////////// ////// ////// ///////////////// TRADE Functions /////// ///////////////// ///////////////////////|
| |||
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |||
//+----------------------------------------------------------------------------------------------------------------------------------------------------------------
| |||
| |||
void Enter_Pos(){
| |||
if (m_entry_mode != 0 && m_entry_mode != 1 ){
| |||
if( Calc_Stop_levels() == -1) return;
| |||
Calc_Lot_Size();
| |||
ExecuteTrade();
| |||
Set_Nums();
| |||
UI_Post();
| |||
}
| |||
}
| |||
| |||
void Exit_Pos(){
| |||
/// imstead of manual close just chechk exit prices
| |||
if (PositionsTotal() == 0)
| |||
Re_setNums();
| |||
}
| |||
| |||
void Edit_Pos(){
| |||
// for changing sl and Tp based on GUI Interation
| |||
}
| |||
| |||
bool ExecuteTrade(){
| |||
bool executed = false;
| |||
| |||
if (m_direction == ORDER_TYPE_BUY)
| |||
if (Trade.Buy(lot_,_Symbol,ask,sl_,tp_))
| |||
executed = true;
| |||
| |||
if (m_direction == ORDER_TYPE_SELL)
| |||
if (Trade.Sell(lot_,_Symbol,bid,sl_,tp_))
| |||
executed = true;
| |||
| |||
return executed ;
| |||
| |||
}
| |||
| |||
void Calc_Lot_Size(){
| |||
| |||
lot_ = (m_direction == ORDER_TYPE_BUY)
| |||
? NormalizeDouble( m_risk_dollars/(bid-sl_ + spread), 2)
| |||
: NormalizeDouble (m_risk_dollars/(sl_-bid + spread), 2 ) ;
| |||
| |||
//Print ( NormalizeDouble ( m_risk_dollars/((bid-sl_) * 100000), 2) );
| |||
| |||
if (lot_ > 10){ // max lot will be calculated first based on martingale step and size stop loss size
| |||
lot_ = 10;
| |||
}
| |||
| |||
// min lot for small acounts
| |||
| |||
Print("(m_direction == ORDER_TYPE_BUY ::::: " ,m_direction == ORDER_TYPE_BUY );
| |||
Print("LOT_ ::::: " , lot_ );
| |||
}
| |||
| |||
bool Calc_Stop_levels(){
| |||
| |||
if (m_direction == ORDER_TYPE_BUY) {
| |||
| |||
double price_d = MathAbs(ask - rates[0].low );
| |||
Print(":::::::::: :::::::::::: :::::::::::: ::::::::: ");
| |||
Print("sl Distance in Pips ::::: " , price_d ); // dont have to worry about sprea d hear as its handeled in lot calculation
| |||
//Print("last low ::::: " , rates[0].low);
| |||
sl_ = (price_d < m_min_sl_points/100) //(price_d < m_max_sl_points && price_d > m_min_sl_points )
| |||
? bid - (m_min_sl_points/100)
| |||
: (price_d < m_max_sl_points/100)
| |||
? bid - m_max_sl_points/100
| |||
: 1
| |||
;
| |||
//for exact sl_ when not using snap method
| |||
//? MathMax( rates[0].low - sl_buffer , ask - m_max_sl_points )
| |||
//: rates[0].low ;
| |||
tp_ = bid + (bid-sl_) * R2r;
| |||
| |||
| |||
}else{
| |||
| |||
double price_d = MathAbs(bid - sellKey_buffer[1]);
| |||
sl_ = (price_d < m_max_sl_points && ( price_d > m_min_sl_points) )
| |||
? MathMin( sellKey_buffer[1] + sl_buffer , bid + m_max_sl_points )
| |||
: -1 ;
| |||
tp_ = ask - (sl_-ask) * R2r ;
| |||
| |||
}
| |||
| |||
Print ("sl_ :::::::::" , sl_);
| |||
Print ("tp_ :::::::::" , tp_);
| |||
| |||
return (sl_ != 1) ;
| |||
| |||
}
| |||
| |||
| |||
void Set_Nums(){
| |||
/// plenty is implicityly set but for tracking and switching
| |||
}
| |||
| |||
void Re_setNums(){
| |||
| |||
if (m_trials == 0 )
| |||
m_is_active = false;
| |||
else
| |||
m_trials-- ;
| |||
| |||
ObjectDelete(0,"SL_");
| |||
ObjectDelete(0,"TP_");
| |||
m_is_active = true ;
| |||
}
| |||
| |||
| |||
| |||
| |||
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |||
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |||
//|//////////// ////// ////// ///////////////// TRACKERS AND INFO ////////// ///////////////// ///////////////////////|
| |||
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |||
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |||
| |||
| |||
| |||
| |||
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |||
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |||
//|//////////// ////// ////// ////////////////////// GUI ////////// ///////////////// //////////////////////////|
| |||
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |||
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |||
//*********************************************************************************************
| |||
//*********************************************************************************************
| |||
//*********************************************************************************************
| |||
//******************************************
| |||
//+-------------------------------------------------------------------------------------------+
| |||
//+-------------------------------------------------------------------------------------------+
| |||
//|///////////////// GUI Initializers ///////////////////////|
| |||
//+-------------------------------------------------------------------------------------------+
| |||
//+-------------------------------------------------------------------------------------------+
| |||
// Input Parameters (The only user inputs that are not controlled by the panel)
| |||
input string Inp_Unique_ID = "HA_PANEL_EA_123";// Unique ID for panel objects
| |||
input int Inp_Panel_X_Corner = 5; // Panel X-coordinate
| |||
input int Inp_Panel_Y_Corner = 5; // Panel Y-coordinate
| |||
| |||
// --- GUI Objects Pointers ---
| |||
CAppDialog *app ;
| |||
CLabel *m_label_title;
| |||
CButton *m_button_activate;
| |||
CButton *m_button_deactivate;
| |||
CComboBox *m_combo_direction;
| |||
CComboBox *m_combo_entry_mode;
| |||
CEdit *m_edit_risk;
| |||
CEdit *m_edit_max_sl;
| |||
CEdit *m_edit_rr;
| |||
CEdit *m_edit_trials;
| |||
CLabel *m_label_status;
| |||
| |||
| |||
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| GUI Creation Function |
| |||
//+------------------------------------------------------------------+
| |||
bool LOAD_GUI(){
| |||
| |||
int x = Inp_Panel_X_Corner;
| |||
int y = Inp_Panel_Y_Corner;
| |||
int row_height = 25;
| |||
int label_width = 150;
| |||
int padding = 10;
| |||
int control_width = label_width * 2 + 10 ;
| |||
| |||
app = new CAppDialog();
| |||
app.Create(0,Inp_Unique_ID + " HKL PANEL ",0,x,y, x + control_width + padding *2 , y + 250);
| |||
| |||
| |||
// --- Direction (Label & Combo) ---
| |||
m_label_title = new CLabel();
| |||
m_label_title.Create(0,Inp_Unique_ID + "_DIR_LBL",0,x,y,label_width,row_height);
| |||
m_label_title.Text("Trade Direction");
| |||
app.Add(m_label_title);
| |||
| |||
| |||
m_combo_direction = new CComboBox();
| |||
m_combo_direction.Create(0,Inp_Unique_ID + "_DIR_COMBO",0,x + label_width + padding ,y ,x + control_width ,y + row_height);
| |||
m_combo_direction.AddItem("BUY Only");
| |||
m_combo_direction.AddItem("SELL Only");
| |||
m_combo_direction.Select(m_direction);
| |||
app.Add(m_combo_direction);
| |||
ObjectSetInteger(0,Inp_Unique_ID + "_DIR_COMBO",OBJPROP_ZORDER,100000000000000000000000000000);
| |||
| |||
y += row_height + padding;
| |||
| |||
// --- Entry Mode (Label & Combo) ---
| |||
m_label_title = new CLabel(); // Corrected instantiation and variable name
| |||
m_label_title.Create(0, Inp_Unique_ID + "_MODE_LBL", 0, x, y, label_width, row_height); // Create with correct dimensions and ID
| |||
m_label_title.Text("Entry Condition"); // Set the text
| |||
app.Add(m_label_title); // Add the label to the dialog/app
| |||
| |||
m_combo_entry_mode = new CComboBox(); // Corrected instantiation
| |||
m_combo_entry_mode.Create(0, Inp_Unique_ID + "_MODE_COMBO", 0, x + label_width +padding , y,x + control_width, y+ row_height); // Create with correct position (after label) and ID
| |||
| |||
// Add Items
| |||
m_combo_entry_mode.AddItem("HA Blue");
| |||
m_combo_entry_mode.AddItem("HA Red");
| |||
m_combo_entry_mode.AddItem("HA Blue && Prev Blue (Confirm Buy)");
| |||
m_combo_entry_mode.AddItem("HA Red && Prev Red (Confirm Sell)");
| |||
m_combo_entry_mode.AddItem("Next BUY KEY (HA Blue)");
| |||
m_combo_entry_mode.AddItem("Next SELL KEY (HA Red)");
| |||
| |||
m_combo_entry_mode.Select(m_entry_mode); // Select item based on existing variable m_entry_mode (as inferred from the original uncommented code's pattern)
| |||
app.Add(m_combo_entry_mode); // Add the combobox to the dialog/app
| |||
| |||
y += row_height + padding; // Update the y-coordinate for the next control
| |||
| |||
| |||
// --- Risk Amount (Label & Edit) ---
| |||
m_label_title = new CLabel(); // Using m_label_title as the name
| |||
m_label_title.Create(0, Inp_Unique_ID + "_RISK_LBL", 0, x, y, label_width, row_height);
| |||
m_label_title.Text("Risk Amount ($)");
| |||
app.Add(m_label_title); // Add the label to the dialog/app
| |||
| |||
m_edit_risk = new CEdit();
| |||
m_edit_risk.Create(0, Inp_Unique_ID + "_RISK_EDIT", 0, x + label_width + padding, y, x + control_width, y + row_height);
| |||
m_edit_risk.Text(DoubleToString(m_risk_dollars, 2));
| |||
app.Add(m_edit_risk); // Add the edit box to the dialog/app
| |||
| |||
y += row_height + padding; // Update the y-coordinate
| |||
| |||
| |||
// --- Max SL (Label & Edit) ---
| |||
m_label_title = new CLabel(); // Using m_label_title as the name
| |||
m_label_title.Create(0, Inp_Unique_ID + "_MAXSL_LBL", 0, x, y, label_width, row_height);
| |||
m_label_title.Text("Max SL (Points)");
| |||
app.Add(m_label_title); // Add the label to the dialog/app
| |||
| |||
m_edit_max_sl = new CEdit(); // Corrected instantiation
| |||
m_edit_max_sl.Create(0, Inp_Unique_ID + "_MAXSL_EDIT", 0, x + label_width + padding, y, x + control_width, y + row_height);
| |||
m_edit_max_sl.Text(DoubleToString(m_max_sl_points, 0));
| |||
app.Add(m_edit_max_sl); // Add the edit box to the dialog/app
| |||
| |||
y += row_height + padding; // Update the y-coordinate
| |||
| |||
// --- R:R Ratio (Label & Edit) ---
| |||
m_label_title = new CLabel(); // Using m_label_title as the name
| |||
m_label_title.Create(0, Inp_Unique_ID + "_RR_LBL", 0, x, y, label_width, row_height);
| |||
m_label_title.Text("Risk to Reward Ratio (R:r)");
| |||
app.Add(m_label_title); // Add the label to the dialog/app
| |||
| |||
m_edit_rr = new CEdit(); // Corrected instantiation
| |||
m_edit_rr.Create(0, Inp_Unique_ID + "_RR_EDIT", 0, x + label_width + padding, y, x + control_width, y + row_height);
| |||
m_edit_rr.Text(DoubleToString(R2r, 2));
| |||
app.Add(m_edit_rr); // Add the edit box to the dialog/app
| |||
| |||
y += row_height + padding; // Update the y-coordinate
| |||
| |||
| |||
// --- Trials (Label & Edit) ---
| |||
m_label_title = new CLabel(); // Using m_label_title as the name
| |||
m_label_title.Create(0, Inp_Unique_ID + "_Trials_LBL", 0, x, y, label_width, row_height);
| |||
m_label_title.Text("Try");
| |||
app.Add(m_label_title); // Add the label to the dialog/app
| |||
| |||
m_edit_trials = new CEdit(); // Corrected instantiation
| |||
m_edit_trials.Create(0, Inp_Unique_ID + "_Trials_edit", 0, x + label_width + padding, y, x + control_width, y + row_height);
| |||
m_edit_trials.Text(DoubleToString(m_trials, 2));
| |||
app.Add(m_edit_trials); // Add the edit box to the dialog/app
| |||
| |||
y += row_height + padding; // Update the y-coordinate
| |||
| |||
// --- Activate Button ---
| |||
m_button_activate = new CButton(); // Correct instantiation
| |||
m_button_activate.Create(0, Inp_Unique_ID + "_ACTIVATE_BTN", 0, x, y, x + control_width ,y + row_height);
| |||
m_button_activate.Text("ACTIVATE");
| |||
m_button_activate.Color(clrGreen); // Green, as noted in original comment
| |||
app.Add(m_button_activate); // Add the button to the dialog/app
| |||
| |||
y += row_height * 1.5 + padding;
| |||
| |||
m_label_status = new CLabel();
| |||
m_label_status.Create(0, Inp_Unique_ID + "_STATUS_LBL", 0, x + 40, y, x + control_width ,y + row_height);
| |||
m_label_status.Color(clrMagenta);
| |||
m_label_status.Font("Arial Bold");
| |||
| |||
| |||
app.Run();
| |||
return true;
| |||
| |||
}
| |||
| |||
//+-------------------------------------------------------------------------------------------+
| |||
//+-------------------------------------------------------------------------------------------+
| |||
//|///////////////// OnChartEvent ///////////////////////|
| |||
//+-------------------------------------------------------------------------------------------+
| |||
//+-------------------------------------------------------------------------------------------+
| |||
| |||
void OnChartEvent(const int id,
| |||
const long &lparam,
| |||
const double &dparam,
| |||
const string &sparam)
| |||
{
| |||
// 1. MUST pass all chart events to the dialog first so it can open/close dropdowns
| |||
if(CheckPointer(app) != POINTER_INVALID)
| |||
app.ChartEvent(id, lparam, dparam, sparam);
| |||
| |||
// 2. Handle Custom Control Changes (Selection / Button clicks)
| |||
if(id == CHARTEVENT_CUSTOM + ON_CHANGE)
| |||
{
| |||
// Direction Combo Selection
| |||
if(lparam == m_combo_direction.Id())
| |||
{
| |||
int index = (int)m_combo_direction.Select();
| |||
if(index >= 0 && index <= DIR_BOTH)
| |||
{
| |||
m_direction = (ENUM_DIRECTION)index;
| |||
Print("Direction changed to: ", EnumToString_(m_direction));
| |||
}
| |||
UpdateStatusLabel();
| |||
return;
| |||
}
| |||
| |||
// Entry Mode Combo Selection
| |||
if(lparam == m_combo_entry_mode.Id())
| |||
{
| |||
int index = (int)m_combo_entry_mode.Select();
| |||
if(index >= 0 && index <= MODE_NEXT_SELL_KEY)
| |||
{
| |||
m_entry_mode = (ENUM_ENTRY_MODE)index;
| |||
Print("Entry Mode changed to: ", EnumToString_(m_entry_mode));
| |||
}
| |||
UpdateStatusLabel();
| |||
return;
| |||
}
| |||
| |||
// Edit box changes
| |||
if(lparam == m_edit_risk.Id())
| |||
{
| |||
double new_risk = StringToDouble(m_edit_risk.Text());
| |||
if(new_risk > 0.0) m_risk_dollars = new_risk;
| |||
else m_edit_risk.Text(DoubleToString(m_risk_dollars, 2));
| |||
}
| |||
| |||
if(lparam == m_edit_max_sl.Id())
| |||
{
| |||
double new_sl = StringToDouble(m_edit_max_sl.Text());
| |||
if(new_sl > 0.0) m_max_sl_points = new_sl;
| |||
else m_edit_max_sl.Text(DoubleToString(m_max_sl_points, 0));
| |||
}
| |||
| |||
if(lparam == m_edit_rr.Id())
| |||
{
| |||
double new_rr = StringToDouble(m_edit_rr.Text());
| |||
if(new_rr >= 1.0) R2r = new_rr;
| |||
else m_edit_rr.Text(DoubleToString(R2r, 1));
| |||
}
| |||
| |||
UpdateStatusLabel();
| |||
return;
| |||
}
| |||
| |||
// 3. Handle Button Click Events
| |||
if(id == CHARTEVENT_CUSTOM + ON_CLICK)
| |||
{
| |||
if(lparam == m_button_activate.Id())
| |||
{
| |||
m_is_active = !m_is_active; // Toggle activation
| |||
Print("EA Active State: ", m_is_active);
| |||
UpdateStatusLabel();
| |||
return;
| |||
}
| |||
}
| |||
}
| |||
| |||
| |||
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Updates the GUI status label |
| |||
//+------------------------------------------------------------------+
| |||
void UpdateStatusLabel()
| |||
{
| |||
if (m_label_status == NULL) return;
| |||
| |||
string status_text = m_is_active ? "STATUS: ACTIVE" : "STATUS: DEACTIVATED";
| |||
color status_color = m_is_active ? clrGreen : clrRed;
| |||
color status_Bcolor = m_is_active ? clrLightGreen : clrPink;
| |||
| |||
| |||
// Add configuration summary to the status label
| |||
status_text += "\n" + EnumToString_(m_direction) + " | " + EnumToString_(m_entry_mode);
| |||
| |||
m_label_status.Text(status_text);
| |||
m_button_activate.Color(status_color);
| |||
m_button_activate.ColorBorder(status_color);
| |||
| |||
ChartRedraw();
| |||
}
| |||
| |||
| |||
| |||
| |||
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| EA Deinitialization Function |
| |||
//+------------------------------------------------------------------+
| |||
void OnDeinit(const int reason)
| |||
{
| |||
// Clean up all chart objects when the EA is removed
| |||
ObjectsDeleteAll(0, Inp_Unique_ID + "*");
| |||
| |||
// Delete GUI objects
| |||
ObjectDelete(0,"SL_");
| |||
ObjectDelete(0,"TP_");
| |||
delete m_label_title;
| |||
delete m_button_activate;
| |||
delete m_button_deactivate;
| |||
delete m_combo_direction;
| |||
delete m_combo_entry_mode;
| |||
delete m_edit_risk;
| |||
delete m_edit_max_sl;
| |||
delete m_edit_rr;
| |||
delete m_label_status;
| |||
delete app;
| |||
| |||
}
| |||
| |||
| |||
void UI_Post(){
| |||
| |||
ObjectCreate(0,"SL_", OBJ_HLINE,0,0,sl_);
| |||
ObjectSetInteger(0,"SL_",OBJPROP_COLOR,clrRed);
| |||
ObjectCreate(0,"TP_", OBJ_HLINE,0,0,tp_);
| |||
ObjectSetInteger(0,"Tp_",OBJPROP_COLOR,clrRed);
| |||
}
| |||
| |||
| |||
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |||
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |||
//|//////////// ////// ////// ///////////////// HELPER FUNCTIONS /////// ///////////////// //////////////////////|
| |||
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |||
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |||
| |||
int PositionsTotal_(){
| |||
| |||
if (PositionsTotal() == 0 ) return 0;
| |||
int count = 0;
| |||
| |||
for (int i = PositionsTotal() - 1; i >= 0; i--){
| |||
ulong ticket = PositionGetTicket(i);
| |||
if (!PositionSelectByTicket(ticket))
| |||
continue;
| |||
if (PositionGetInteger(POSITION_MAGIC) != magicnumber)
| |||
continue;
| |||
if (PositionGetString(POSITION_SYMBOL) != _Symbol)
| |||
continue;
| |||
count++;
| |||
}
| |||
| |||
return count ;
| |||
}
| |||
| |||
string EnumToString_(const int value)
| |||
{
| |||
if (value == DIR_BUY) return "BUY Only";
| |||
if (value == DIR_SELL) return "SELL Only";
| |||
if (value == MODE_HA_BLUE_ONLY) return "HA Blue";
| |||
if (value == MODE_HA_RED_ONLY) return "HA Red";
| |||
if (value == MODE_HA_BLUE_CONFIRM) return "HA Blue Confirm";
| |||
if (value == MODE_HA_RED_CONFIRM) return "HA Red Confirm";
| |||
if (value == MODE_NEXT_BUY_KEY) return "Next BUY KEY";
| |||
if (value == MODE_NEXT_SELL_KEY) return "Next SELL KEY";
| |||
return "UNKNOWN";
| |||
}
|