159 lines
No EOL
9.5 KiB
MQL5
159 lines
No EOL
9.5 KiB
MQL5
#property strict
|
|
|
|
#include <Trade/Trade.mqh>
|
|
CTrade trade;
|
|
|
|
//--- object names
|
|
string BTN_NAME = "CreateLineButton";
|
|
string LINE_NAME = "EntryLine";
|
|
|
|
//--- trend settings
|
|
input int TrendPeriod = 50;
|
|
int ma_handle = INVALID_HANDLE;
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert initialization |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
CreateButton();
|
|
|
|
ma_handle = iMA(_Symbol, _Period, TrendPeriod, 0, MODE_SMA, PRICE_CLOSE);
|
|
if(ma_handle == INVALID_HANDLE)
|
|
{
|
|
Print("MA handle creation failed");
|
|
return INIT_FAILED;
|
|
}
|
|
|
|
return INIT_SUCCEEDED;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert deinitialization |
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason)
|
|
{
|
|
ObjectDelete(0, BTN_NAME);
|
|
ObjectDelete(0, LINE_NAME);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Create button |
|
|
//+------------------------------------------------------------------+
|
|
void CreateButton()
|
|
{
|
|
if(ObjectFind(0, BTN_NAME) != -1)
|
|
return;
|
|
|
|
if(!ObjectCreate(0, BTN_NAME, OBJ_BUTTON, 0, 0, 0))
|
|
{
|
|
Print("Failed to create button");
|
|
return;
|
|
}
|
|
|
|
ObjectSetInteger(0, BTN_NAME, OBJPROP_XDISTANCE, 10);
|
|
ObjectSetInteger(0, BTN_NAME, OBJPROP_YDISTANCE, 20);
|
|
ObjectSetInteger(0, BTN_NAME, OBJPROP_XSIZE, 140);
|
|
ObjectSetInteger(0, BTN_NAME, OBJPROP_YSIZE, 30);
|
|
ObjectSetString(0, BTN_NAME, OBJPROP_TEXT, "Add Entry Line");
|
|
ObjectSetInteger(0, BTN_NAME, OBJPROP_COLOR, clrWhite);
|
|
ObjectSetInteger(0, BTN_NAME, OBJPROP_BGCOLOR, clrBlue);
|
|
ObjectSetInteger(0, BTN_NAME, OBJPROP_BORDER_COLOR, clrBlack);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Create draggable horizontal line |
|
|
//+------------------------------------------------------------------+
|
|
void CreateEntryLine()
|
|
{
|
|
if(ObjectFind(0, LINE_NAME) != -1)
|
|
return;
|
|
|
|
double price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
|
|
|
if(!ObjectCreate(0, LINE_NAME, OBJ_HLINE, 0, 0, price))
|
|
{
|
|
Print("Failed to create line");
|
|
return;
|
|
}
|
|
|
|
ObjectSetInteger(0, LINE_NAME, OBJPROP_COLOR, clrRed);
|
|
ObjectSetInteger(0, LINE_NAME, OBJPROP_WIDTH, 2);
|
|
ObjectSetInteger(0, LINE_NAME, OBJPROP_SELECTABLE, true);
|
|
ObjectSetInteger(0, LINE_NAME, OBJPROP_SELECTED, true);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Chart event handler |
|
|
//+------------------------------------------------------------------+
|
|
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
|
|
{
|
|
if(id == CHARTEVENT_OBJECT_CLICK)
|
|
{
|
|
Print("ChartEvent: clicked object = ", sparam);
|
|
if(sparam == BTN_NAME)
|
|
{
|
|
Print("Button clicked → creating line");
|
|
CreateEntryLine();
|
|
}
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Trend direction using MA |
|
|
//+------------------------------------------------------------------+
|
|
int GetTrendDirection()
|
|
{
|
|
if(ma_handle == INVALID_HANDLE)
|
|
return 0;
|
|
|
|
double ma_buf[1];
|
|
if(CopyBuffer(ma_handle, 0, 0, 1, ma_buf) != 1)
|
|
return 0;
|
|
|
|
double ma = ma_buf[0];
|
|
double price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
|
|
|
if(price > ma) return 1; // uptrend
|
|
if(price < ma) return -1; // downtrend
|
|
return 0;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| OnTick: keep UI alive + trade logic |
|
|
//+------------------------------------------------------------------+
|
|
void OnTick()
|
|
{
|
|
// In tester, chart can reset → ensure button exists
|
|
if(ObjectFind(0, BTN_NAME) == -1)
|
|
CreateButton();
|
|
|
|
if(ObjectFind(0, LINE_NAME) == -1)
|
|
return;
|
|
|
|
double linePrice = ObjectGetDouble(0, LINE_NAME, OBJPROP_PRICE);
|
|
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
|
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
|
|
|
int trend = GetTrendDirection();
|
|
if(trend == 0)
|
|
return;
|
|
|
|
if((trend == 1 && ask >= linePrice) || (trend == -1 && bid <= linePrice))
|
|
{
|
|
double lot = 0.1;
|
|
|
|
if(trend == 1)
|
|
{
|
|
Print("Buying at line touch");
|
|
trade.Buy(lot, _Symbol);
|
|
}
|
|
else
|
|
{
|
|
Print("Selling at line touch");
|
|
trade.Sell(lot, _Symbol);
|
|
}
|
|
|
|
ObjectDelete(0, LINE_NAME);
|
|
}
|
|
} |