Advertisement
cjmt2

SmartCandleEA

Jun 19th, 2025 (edited)
9
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.02 KB | None | 0 0
  1.  
  2. //+-------------------------------------------------------------------------------------+
  3. //| SmartCandleEA.mq5 |
  4. //| https://pastebin.com/cRhQ7rYz |
  5. //+-------------------------------------------------------------------------------------+
  6. #property copyright "ChatGPT"
  7. #property version "1.01"
  8. #property strict
  9. #define ColorAqua clrAqua
  10. #define ColorRed clrRed
  11.  
  12. input double Lots = 0.01;
  13. input double SL_Points = 890; // stop loss in points
  14. input double TP_Points = 910; // take profit in points
  15. input double TrailStart = 690; // trailing start in points
  16. input double TrailStep = 900; // trailing step in points
  17.  
  18. //--- simbolul curent
  19. string symbol;
  20.  
  21. //--- handle-uri pentru timeframe-uri
  22. ENUM_TIMEFRAMES tfH1 = PERIOD_H1;
  23. ENUM_TIMEFRAMES tfH4 = PERIOD_H4;
  24. ENUM_TIMEFRAMES tfD1 = PERIOD_D1;
  25. ENUM_TIMEFRAMES tfW1 = PERIOD_W1;
  26.  
  27. //--- nume obiecte grafice
  28. string objNameH1 = "H1";
  29. string objNameH4 = "H4";
  30. string objNameD1 = "D1";
  31. string objNameW1 = "W1";
  32.  
  33. // stochastic
  34. double Karray[],Darray[];
  35. //defining the stochastic indicator
  36. int StochDef = iStochastic(_Symbol,_Period,14,3,3,MODE_SMA,STO_LOWHIGH);
  37.  
  38. //+------------------------------------------------------------------+
  39. //| Expert initialization function |
  40. //+------------------------------------------------------------------+
  41. int OnInit()
  42. {
  43. symbol = _Symbol;
  44. //ChartSetInteger(0, CHART_SHOW_PERIOD_SEPARATORS, false); // ascunde liniile perioadelor pentru claritate
  45.  
  46. // curata obiecte vechi
  47. ObjectDelete(0,objNameH1);
  48. ObjectDelete(0,objNameH4);
  49. ObjectDelete(0,objNameD1);
  50. ObjectDelete(0,objNameW1);
  51.  
  52. return(INIT_SUCCEEDED);
  53. }
  54.  
  55. //+------------------------------------------------------------------+
  56. //| Functie pentru obtinerea valorilor OHLC pentru o anumita TF |
  57. //+------------------------------------------------------------------+
  58. bool GetOHLC(ENUM_TIMEFRAMES tf, datetime &time_open, double &open, double &high, double &low, double &close)
  59. {
  60. MqlRates rates[];
  61. if(CopyRates(symbol, tf, 0, 1, rates) != 1)
  62. return(false);
  63.  
  64. time_open = rates[0].time;
  65. open = rates[0].open;
  66. high = rates[0].high;
  67. low = rates[0].low;
  68. close = rates[0].close;
  69. return(true);
  70. }
  71.  
  72. //+------------------------------------------------------------------+
  73. //| Functie desenare candela suprapusa pe M1 |
  74. //+------------------------------------------------------------------+
  75. void DrawCandleOverlay(string name, datetime time_open, double open, double high, double low, double close, color col)
  76. {
  77. // Șterge obiectul vechi daca exista
  78. ObjectDelete(0,name);
  79.  
  80. // Creaza un obiect rectangle pe grafic cu următoarele coordonate:
  81. // pe orizontala, de la time_open pana la timpul curent (acum)
  82. // pe verticala, intre low si high
  83.  
  84. datetime time_now = TimeCurrent();
  85.  
  86. // creeaza rectangle
  87. if(!ObjectCreate(0, name, OBJ_RECTANGLE, 0, time_open, high, time_now, low))
  88. {
  89. Print("Eroare la crearea obiectului ", name);
  90. return;
  91. }
  92.  
  93. // setari vizuale
  94. ObjectSetInteger(0, name, OBJPROP_COLOR, col);
  95. ObjectSetInteger(0, name, OBJPROP_BACK, true); // sa fie in spate
  96. ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_SOLID);
  97. ObjectSetInteger(0, name, OBJPROP_WIDTH, 2);
  98.  
  99. // Opacitate in functie de close > open
  100. if(close > open)
  101. ObjectSetInteger(0, name, OBJPROP_BGCOLOR, ColorToARGB(ColorAqua, 60));
  102. else
  103. ObjectSetInteger(0, name, OBJPROP_BGCOLOR, ColorToARGB(ColorRed, 60));
  104. }
  105.  
  106. //+-----------------------------------------------------------------+
  107. //| Functie pentru conversia culorii cu opacitate |
  108. //+-----------------------------------------------------------------+
  109. ulong ColorToARGBAlpha(color c, uchar alpha)
  110. {
  111. return(((ulong)alpha << 24) | ((ulong)c & 0xFFFFFF));
  112. }
  113.  
  114. //+------------------------------------------------------------------+
  115. //| Verifica regula simpla de intrare |
  116. //+------------------------------------------------------------------+
  117. int CheckTradeSignal()
  118. {
  119. datetime t_open;
  120. double open, high, low, close;
  121.  
  122. // Preluam OHLC pentru fiecare timeframe
  123. if(!GetOHLC(tfH1, t_open, open, high, low, close)) return 0;
  124. bool h1Buy = (close > open);
  125. bool h1Sell = (close < open);
  126.  
  127. if(!GetOHLC(tfH4, t_open, open, high, low, close)) return 0;
  128. bool h4Buy = (close > open);
  129. bool h4Sell = (close < open);
  130.  
  131. if(!GetOHLC(tfD1, t_open, open, high, low, close)) return 0;
  132. bool d1Buy = (close > open);
  133. bool d1Sell = (close < open);
  134.  
  135. if(!GetOHLC(tfW1, t_open, open, high, low, close)) return 0;
  136. bool w1Buy = (close > open);
  137. bool w1Sell = (close < open);
  138.  
  139. // stochastic
  140. //sorting arrays from the current data
  141. ArraySetAsSeries(Karray, true);
  142. ArraySetAsSeries(Darray, true);
  143. //filling arrays with price data
  144. CopyBuffer(StochDef,0,0,3,Karray);
  145. CopyBuffer(StochDef,1,0,3,Darray);
  146. //calculating value of %K and %D line of cuurent data
  147. double KValue0 = Karray[0];
  148. double DValue0 = Darray[0];
  149. double KValue1 = Karray[1];
  150. double DValue1 = Darray[1];
  151.  
  152. // Conditii pentru BUY: toate in sus
  153. if(h1Buy && h4Buy && d1Buy && w1Buy && KValue0 < 20 && DValue0 < 20 && KValue0 > DValue0 && KValue1 < DValue1) return 1;
  154.  
  155. // Conditii pentru SELL: toate in jos
  156. if(h1Sell && h4Sell && d1Sell && w1Sell && KValue0 > 80 && DValue0 > 80 && KValue0 < DValue0 && KValue1 > DValue1) return -1;
  157.  
  158. return 0; // fara semnal clar
  159. }
  160.  
  161. //+------------------------------------------------------------------+
  162. //| Functie executie ordine BUY |
  163. //+------------------------------------------------------------------+
  164. bool OpenBuy()
  165. {
  166. double price = SymbolInfoDouble(symbol, SYMBOL_ASK);
  167. double sl = price - SL_Points * _Point;
  168. double tp = price + TP_Points * _Point;
  169.  
  170. MqlTradeRequest request;
  171. MqlTradeResult result;
  172. ZeroMemory(request);
  173. ZeroMemory(result);
  174.  
  175. request.action = TRADE_ACTION_DEAL;
  176. request.symbol = symbol;
  177. request.volume = Lots;
  178. request.type = ORDER_TYPE_BUY;
  179. request.price = price;
  180. request.sl = sl;
  181. request.tp = tp;
  182. request.deviation= 10;
  183. request.magic = 123456;
  184. request.comment = "SmartCandleEA_Buy";
  185.  
  186. if(!OrderSend(request, result))
  187. {
  188. Print("Eroare la deschiderea BUY: ", GetLastError());
  189. return false;
  190. }
  191. Print("Buy deschis la ", price);
  192. return true;
  193. }
  194.  
  195. //+------------------------------------------------------------------+
  196. //| Functie executie ordine SELL |
  197. //+------------------------------------------------------------------+
  198. bool OpenSell()
  199. {
  200. double price = SymbolInfoDouble(symbol, SYMBOL_BID);
  201. double sl = price + SL_Points * _Point;
  202. double tp = price - TP_Points * _Point;
  203.  
  204. MqlTradeRequest request;
  205. MqlTradeResult result;
  206. ZeroMemory(request);
  207. ZeroMemory(result);
  208.  
  209. request.action = TRADE_ACTION_DEAL;
  210. request.symbol = symbol;
  211. request.volume = Lots;
  212. request.type = ORDER_TYPE_SELL;
  213. request.price = price;
  214. request.sl = sl;
  215. request.tp = tp;
  216. request.deviation= 10;
  217. request.magic = 154326;
  218. request.comment = "SmartCandleEA_Sell";
  219.  
  220. if(!OrderSend(request, result))
  221. {
  222. Print("Eroare la deschiderea SELL: ", GetLastError());
  223. return false;
  224. }
  225. Print("Sell deschis la ", price);
  226. return true;
  227. }
  228.  
  229. //+------------------------------------------------------------------+
  230. //| Functie de gestionare a trailing stop |
  231. //+------------------------------------------------------------------+
  232. void ManageTrailingStop()
  233. {
  234. ulong magic = 123456;
  235. for(int i=PositionsTotal()-1; i>=0; i--)
  236. {
  237. ulong ticket = PositionGetTicket(i);
  238. if(PositionGetInteger(POSITION_MAGIC) != magic) continue;
  239. if(PositionGetString(POSITION_SYMBOL) != symbol) continue;
  240.  
  241. double open_price = PositionGetDouble(POSITION_PRICE_OPEN);
  242. double current_price = SymbolInfoDouble(symbol, (PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY) ? SYMBOL_BID : SYMBOL_ASK);
  243. double sl = PositionGetDouble(POSITION_SL);
  244. ENUM_POSITION_TYPE pos_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
  245.  
  246. // Calculate profit in points
  247. double profit_points = (pos_type==POSITION_TYPE_BUY) ? (current_price - open_price)/_Point : (open_price - current_price)/_Point;
  248.  
  249. if(profit_points > TrailStart)
  250. {
  251. double new_sl;
  252. if(pos_type==POSITION_TYPE_BUY)
  253. {
  254. new_sl = current_price - TrailStep * _Point;
  255. if(new_sl > sl)
  256. {
  257. // modifica SL in trailing
  258. ModifyPositionSL(ticket, new_sl);
  259. }
  260. }
  261. else
  262. {
  263. new_sl = current_price + TrailStep * _Point;
  264. if(new_sl < sl || sl==0)
  265. {
  266. ModifyPositionSL(ticket, new_sl);
  267. }
  268. }
  269. }
  270. }
  271. }
  272.  
  273. //+------------------------------------------------------------------+
  274. //| Modificare SL pozitie |
  275. //+------------------------------------------------------------------+
  276. void ModifyPositionSL(ulong ticket, double new_sl)
  277. {
  278. MqlTradeRequest request;
  279. MqlTradeResult result;
  280. ZeroMemory(request);
  281. ZeroMemory(result);
  282.  
  283. request.action = TRADE_ACTION_SLTP;
  284. request.position = ticket;
  285. request.sl = new_sl;
  286. request.tp = PositionGetDouble(POSITION_TP);
  287.  
  288. if(!OrderSend(request, result))
  289. {
  290. Print("Eroare la modificarea SL: ", GetLastError());
  291. }
  292. else
  293. Print("SL modificat la ", DoubleToString(new_sl, _Digits));
  294. }
  295.  
  296. //+------------------------------------------------------------------+
  297. //| Functia principala OnTick |
  298. //+------------------------------------------------------------------+
  299. void OnTick()
  300. {
  301. // 1. Afisare candela suprapusa pe fiecare timeframe
  302. datetime t_open; double open, high, low, close;
  303. if(GetOHLC(tfH1, t_open, open, high, low, close))
  304. DrawCandleOverlay(objNameH1, t_open, open, high, low, close, (close>open) ? clrAqua : clrRed);
  305.  
  306. if(GetOHLC(tfH4, t_open, open, high, low, close))
  307. DrawCandleOverlay(objNameH4, t_open, open, high, low, close, (close>open) ? clrAqua : clrRed);
  308.  
  309. if(GetOHLC(tfD1, t_open, open, high, low, close))
  310. DrawCandleOverlay(objNameD1, t_open, open, high, low, close, (close>open) ? clrAqua : clrRed);
  311.  
  312. if(GetOHLC(tfW1, t_open, open, high, low, close))
  313. DrawCandleOverlay(objNameW1, t_open, open, high, low, close, (close>open) ? clrAqua : clrRed);
  314.  
  315. //+-------------------------------------------------------------------------+
  316. //|1.1 blocheaza deschiderea de pozitii noi cand corpul candelei e prea mic |
  317. //+-------------------------------------------------------------------------+
  318. if(!CandleHasBody(_Symbol, PERIOD_H1) ||
  319. !CandleHasBody(_Symbol, PERIOD_H4) ||
  320. !CandleHasBody(_Symbol, PERIOD_D1) ||
  321. !CandleHasBody(_Symbol, PERIOD_W1))
  322. {
  323. // Nu deschide ordine
  324. return;
  325. }
  326.  
  327. // 2. Verificam semnalul
  328. int signal = CheckTradeSignal();
  329.  
  330. // 3. Managementul pozitiei
  331. ulong magic = 154326;
  332. bool hasPosition = false;
  333. ENUM_POSITION_TYPE pos_type = POSITION_TYPE_BUY;
  334.  
  335. for(int i=PositionsTotal()-1; i>=0; i--)
  336. {
  337. if(PositionGetInteger(POSITION_MAGIC) != magic) continue;
  338. if(PositionGetString(POSITION_SYMBOL) != symbol) continue;
  339.  
  340. hasPosition = true;
  341. pos_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
  342. break;
  343. }
  344.  
  345. // 4. Executie ordine conform semnalului si pozitiei existente
  346. if(signal == 1) // BUY
  347. {
  348. if(!hasPosition || pos_type == POSITION_TYPE_SELL)
  349. {
  350. // inchidem sell daca exista
  351. if(hasPosition && pos_type == POSITION_TYPE_SELL)
  352. ClosePosition(symbol, POSITION_TYPE_SELL);
  353.  
  354. // deschidem BUY
  355. OpenBuy();
  356. }
  357. }
  358. else if(signal == -1) // SELL
  359. {
  360. if(!hasPosition || pos_type == POSITION_TYPE_BUY)
  361. {
  362. // inchidem buy daca exista
  363. if(hasPosition && pos_type == POSITION_TYPE_BUY)
  364. ClosePosition(symbol, POSITION_TYPE_BUY);
  365.  
  366. // deschidem SELL
  367. OpenSell();
  368. }
  369. }
  370. else
  371. {
  372. // fara semnal inchidem toate pozitiile noastre
  373. if(hasPosition)
  374. CloseAllPositions(symbol, magic);
  375. }
  376.  
  377. // 5. Management trailing stop
  378. ManageTrailingStop();
  379. }
  380.  
  381. //+------------------------------------------------------------------+
  382. //| Inchide pozitie dupa tip |
  383. //+------------------------------------------------------------------+
  384. void ClosePosition(string symb, ENUM_POSITION_TYPE type)
  385. {
  386. for(int i=PositionsTotal()-1; i>=0; i--)
  387. {
  388. if(PositionGetInteger(POSITION_MAGIC) != 154326) continue;
  389. if(PositionGetString(POSITION_SYMBOL) != symb) continue;
  390. if(PositionGetInteger(POSITION_TYPE) != type) continue;
  391.  
  392. ulong ticket = PositionGetTicket(i);
  393. ClosePositionByTicket(ticket);
  394. }
  395. }
  396.  
  397. //+------------------------------------------------------------------+
  398. //| Inchide toate pozitiile pentru simbol si magic |
  399. //+------------------------------------------------------------------+
  400. void CloseAllPositions(string symb, ulong magic)
  401. {
  402. for(int i=PositionsTotal()-1; i>=0; i--)
  403. {
  404. if(PositionGetInteger(POSITION_MAGIC) != magic) continue;
  405. if(PositionGetString(POSITION_SYMBOL) != symb) continue;
  406.  
  407. ulong ticket = PositionGetTicket(i);
  408. ClosePositionByTicket(ticket);
  409. }
  410. }
  411.  
  412. //+------------------------------------------------------------------+
  413. //| Inchide pozitia dupa ticket |
  414. //+------------------------------------------------------------------+
  415. void ClosePositionByTicket(ulong ticket)
  416. {
  417. MqlTradeRequest request;
  418. MqlTradeResult result;
  419. ZeroMemory(request);
  420. ZeroMemory(result);
  421.  
  422. request.action = TRADE_ACTION_CLOSE_BY;
  423. request.position = ticket;
  424.  
  425. if(!OrderSend(request,result))
  426. Print("Eroare inchidere pozitie: ", GetLastError());
  427. else
  428. Print("Pozitie inchisa, ticket: ", ticket);
  429. }
  430.  
  431. //+------------------------------------------------------------------+
  432. //| blocheaza deschiderea de pozitii cand corpul candelei e prea mic |
  433. //+------------------------------------------------------------------+
  434. bool CandleHasBody(string usymbol, ENUM_TIMEFRAMES tf, int shift=0, double minBodyPoints=10)
  435. {
  436. double open = iOpen(usymbol, tf, shift);
  437. double close = iClose(usymbol, tf, shift);
  438. return MathAbs(close - open) * MathPow(10, _Digits) >= minBodyPoints;
  439. }
  440.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement