beast-agent 2.76.5 → 2.77.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/package.json +1 -1
  2. package/src/agent/bots.js +669 -664
  3. package/src/agent/customtools.js +6 -19
  4. package/src/agent/engine.js +55 -307
  5. package/src/agent/seeds/tool-yazma/SKILL.md +13 -16
  6. package/src/agent/skills.js +14 -35
  7. package/src/agent/supertonic.js +622 -0
  8. package/src/agent/tools.js +3 -7
  9. package/src/main.js +77 -6068
  10. package/src/preload.js +2 -17
  11. package/src/renderer/i18n.js +14 -8
  12. package/src/renderer/index.html +0 -297
  13. package/src/renderer/renderer.js +142 -2280
  14. package/src/renderer/style.css +3 -825
  15. package/src/agent/defaulttools/mt5_barlar2/run.js +0 -188
  16. package/src/agent/defaulttools/mt5_barlar2/tool.json +0 -23
  17. package/src/agent/defaulttools/mt5_bekleyen/run.js +0 -105
  18. package/src/agent/defaulttools/mt5_bekleyen/tool.json +0 -18
  19. package/src/agent/defaulttools/mt5_durum/run.js +0 -93
  20. package/src/agent/defaulttools/mt5_durum/tool.json +0 -10
  21. package/src/agent/defaulttools/mt5_emir/run.js +0 -98
  22. package/src/agent/defaulttools/mt5_emir/tool.json +0 -17
  23. package/src/agent/defaulttools/mt5_emir_iptal/run.js +0 -90
  24. package/src/agent/defaulttools/mt5_emir_iptal/tool.json +0 -12
  25. package/src/agent/defaulttools/mt5_fiyat/run.js +0 -87
  26. package/src/agent/defaulttools/mt5_fiyat/tool.json +0 -16
  27. package/src/agent/defaulttools/mt5_gecmis/run.js +0 -87
  28. package/src/agent/defaulttools/mt5_gecmis/tool.json +0 -12
  29. package/src/agent/defaulttools/mt5_kapat/run.js +0 -108
  30. package/src/agent/defaulttools/mt5_kapat/tool.json +0 -15
  31. package/src/agent/defaulttools/mt5_m15_m5/m15m5.py +0 -60
  32. package/src/agent/defaulttools/mt5_m15_m5/run.js +0 -73
  33. package/src/agent/defaulttools/mt5_m15_m5/tool.json +0 -10
  34. package/src/agent/defaulttools/mt5_pozisyon_gecmis/run.js +0 -144
  35. package/src/agent/defaulttools/mt5_pozisyon_gecmis/tool.json +0 -12
  36. package/src/agent/defaulttools/mt5_shot/run.js +0 -649
  37. package/src/agent/defaulttools/mt5_shot/stitch.js +0 -151
  38. package/src/agent/defaulttools/mt5_shot/tool.json +0 -25
  39. package/src/agent/defaulttools/mt5_sltp/run.js +0 -92
  40. package/src/agent/defaulttools/mt5_sltp/tool.json +0 -14
  41. package/src/agent/financetools.js +0 -1025
  42. package/src/agent/finindicators.js +0 -254
  43. package/src/agent/finrisk.js +0 -289
  44. package/src/agent/finstats.js +0 -239
  45. package/src/agent/finwatch.js +0 -302
  46. package/src/agent/mt5/BeastFinance.mq5 +0 -498
  47. package/src/agent/mt5/BeastShot.tpl +0 -0
  48. package/src/agent/mt5setup.js +0 -542
  49. package/src/agent/scripts/mt5_bridge.py +0 -575
  50. package/src/agent/seeds/haber-duygu/SKILL.md +0 -49
  51. package/src/agent/seeds/mql5/SKILL.md +0 -154
  52. package/src/agent/seeds/price-action/SKILL.md +0 -60
  53. package/src/agent/seeds/risk-yonetimi/SKILL.md +0 -52
  54. package/src/mt5bridge.js +0 -215
@@ -1,575 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- """Beast Finance - MetaTrader 5 stdio koprusu.
4
-
5
- Bilgisayardaki calisan MT5 terminaline MetaTrader5 python paketiyle baglanir.
6
- Stdin'den JSON satirlari okur ({id, method, params}), her istegin yanitini
7
- tek JSON satiri olarak stdout'a yazar ({id, ok, data|error}).
8
- Baglanti olaylarini event satirlari ile bildirir ({event: 'bridge', ...}).
9
-
10
- Gereksinim: pip install MetaTrader5 (yalnizca Windows + MT5 terminal kurulu)
11
- """
12
- import sys
13
- import json
14
- import time
15
- import os
16
- import argparse
17
-
18
- try:
19
- import MetaTrader5 as mt5
20
- except Exception:
21
- mt5 = None
22
-
23
-
24
- def out(obj):
25
- try:
26
- sys.stdout.write(json.dumps(obj, ensure_ascii=False, default=str) + "\n")
27
- sys.stdout.flush()
28
- except Exception:
29
- pass
30
-
31
-
32
- def d(obj):
33
- """namedtuple/dict/list -> sade dict agaci (JSON'a hazir)."""
34
- if obj is None:
35
- return None
36
- if hasattr(obj, "_asdict"):
37
- return {k: d(v) for k, v in obj._asdict().items()}
38
- if isinstance(obj, dict):
39
- return {k: d(v) for k, v in obj.items()}
40
- if isinstance(obj, (list, tuple)):
41
- return [d(x) for x in obj]
42
- return obj
43
-
44
-
45
- TERMINAL_PATH = ""
46
- INIT_TRIED = False
47
- ALLOW_LAUNCH = True # Beast Finance kapaliyken False: MT5 kapaliysa ACILMAZ
48
-
49
-
50
- def ensure_init():
51
- """Terminal baglantisi yoksa (yeniden) init dener; True/False doner.
52
- ALLOW_LAUNCH False iken terminal kapaliysa BASLATMA denenmez — Beast
53
- Finance acilmadikca MT5 kendiliginden acilmaz."""
54
- global INIT_TRIED
55
- if mt5 is None:
56
- return False
57
- try:
58
- if mt5.terminal_info() is not None:
59
- return True
60
- except Exception:
61
- pass
62
- if not ALLOW_LAUNCH:
63
- return False
64
- INIT_TRIED = True
65
- if TERMINAL_PATH:
66
- return bool(mt5.initialize(path=TERMINAL_PATH))
67
- return bool(mt5.initialize())
68
-
69
-
70
- def need():
71
- if mt5 is None:
72
- raise RuntimeError("MetaTrader5 python paketi kurulu degil (pip install MetaTrader5)")
73
- if not ensure_init():
74
- if not ALLOW_LAUNCH:
75
- raise RuntimeError("MT5 terminali kapali — Beast Finance acilinca otomatik baslatilir")
76
- last = ""
77
- try:
78
- last = str(mt5.last_error())
79
- except Exception:
80
- pass
81
- raise RuntimeError("MT5 terminaline baglanilamadi (terminal acik mi?) " + last)
82
-
83
-
84
- # ---------------- yontemler ----------------
85
-
86
- def h_ping(p):
87
- return {"pong": True, "mt5": mt5 is not None, "connected": bool(ensure_init()) if mt5 else False, "launch": ALLOW_LAUNCH}
88
-
89
-
90
- def h_policy(p):
91
- """Otomatik baslatma politikasi: {"launch": bool}. Beast Finance
92
- kapatilinca launch=False gonderilir — MT5 kapaliysa bir daha ACILMAZ;
93
- terminal aciksa cagrilar calismaya devam eder (koruma surer)."""
94
- global ALLOW_LAUNCH
95
- ALLOW_LAUNCH = p.get("launch") is not False
96
- return {"launch": ALLOW_LAUNCH}
97
-
98
-
99
- def h_account(p):
100
- need()
101
- return {"account": d(mt5.account_info())}
102
-
103
-
104
- def h_terminal(p):
105
- need()
106
- return {"terminal": d(mt5.terminal_info())}
107
-
108
-
109
- def h_symbols(p):
110
- need()
111
- syms = p.get("symbols") or []
112
- res = []
113
- for s in syms:
114
- s = str(s).strip().upper()
115
- if not s:
116
- continue
117
- info = mt5.symbol_info(s)
118
- if info is None:
119
- # sembol Market Watch'ta yoksa secmeyi dene
120
- mt5.symbol_select(s, True)
121
- info = mt5.symbol_info(s)
122
- if info is None:
123
- res.append({"symbol": s, "missing": True})
124
- continue
125
- tick = mt5.symbol_info_tick(s)
126
- row = d(info)
127
- row.update(d(tick) or {})
128
- row["symbol"] = s
129
- res.append(row)
130
- return {"symbols": res}
131
-
132
-
133
- def h_positions(p):
134
- need()
135
- return {"positions": d(mt5.positions_get()) or []}
136
-
137
-
138
- def h_orders(p):
139
- need()
140
- return {"orders": d(mt5.orders_get()) or []}
141
-
142
-
143
- def h_deals(p):
144
- need()
145
- days = p.get("days")
146
- try:
147
- days = float(days)
148
- except Exception:
149
- days = 1.0
150
- days = max(0.01, min(days, 90.0))
151
- to = time.time()
152
- frm = to - days * 86400.0
153
- deals = mt5.history_deals_get(frm, to) or []
154
- rows = d(deals)
155
- # sadece pozisyon giris/cikislari: entry 0 giris 1 cikis (DEAL_ENTRY_OUT)
156
- return {"deals": rows[-500:], "count": len(rows)}
157
-
158
-
159
- def _send_request(req):
160
- res = mt5.order_send(req)
161
- if res is None:
162
- raise RuntimeError("order_send None dondu " + str(mt5.last_error()))
163
- r = d(res)
164
- # bazi brokerlar IOC desteklemez: FOK, sonra RETURN ile birer kez tekrar dene
165
- if int(r.get("retcode") or 0) == 10030 and "type_filling" in req:
166
- for filling in (mt5.ORDER_FILLING_FOK, mt5.ORDER_FILLING_RETURN):
167
- if req["type_filling"] == filling:
168
- continue
169
- req2 = dict(req)
170
- req2["type_filling"] = filling
171
- res = mt5.order_send(req2)
172
- if res is None:
173
- continue
174
- r = d(res)
175
- if int(r.get("retcode") or 0) in (10008, 10009):
176
- break
177
- if int(r.get("retcode") or 0) not in (10008, 10009): # PLACED / DONE
178
- raise RuntimeError("islem reddedildi retcode=%s comment=%s" % (r.get("retcode"), r.get("comment")))
179
- return r
180
-
181
-
182
- def h_market(p):
183
- need()
184
- symbol = str(p.get("symbol") or "").strip().upper()
185
- side = str(p.get("side") or "").lower()
186
- volume = float(p.get("volume") or 0)
187
- if not symbol or side not in ("buy", "sell") or volume <= 0:
188
- raise RuntimeError("symbol/side/volume zorunlu")
189
- mt5.symbol_select(symbol, True)
190
- tick = mt5.symbol_info_tick(symbol)
191
- if tick is None:
192
- raise RuntimeError("tick alinamadi: " + symbol)
193
- price = tick.ask if side == "buy" else tick.bid
194
- order_type = mt5.ORDER_TYPE_BUY if side == "buy" else mt5.ORDER_TYPE_SELL
195
- req = {
196
- "action": mt5.TRADE_ACTION_DEAL,
197
- "symbol": symbol,
198
- "volume": volume,
199
- "type": order_type,
200
- "price": price,
201
- "deviation": int(p.get("deviation") or 20),
202
- "magic": int(p.get("magic") or 20260908),
203
- "comment": str(p.get("comment") or "Beast")[:26],
204
- "type_time": mt5.ORDER_TIME_GTC,
205
- "type_filling": mt5.ORDER_FILLING_IOC,
206
- }
207
- if p.get("sl"):
208
- req["sl"] = float(p.get("sl"))
209
- if p.get("tp"):
210
- req["tp"] = float(p.get("tp"))
211
- return {"result": _send_request(req), "price": price}
212
-
213
-
214
- def h_close(p):
215
- need()
216
- ticket = int(p.get("ticket") or 0)
217
- if not ticket:
218
- raise RuntimeError("ticket zorunlu")
219
- pos = mt5.positions_get(ticket=ticket)
220
- if not pos:
221
- raise RuntimeError("pozisyon bulunamadi: %s" % ticket)
222
- pos = pos[0]
223
- volume = float(p.get("volume") or pos.volume)
224
- volume = min(volume, pos.volume)
225
- symbol = pos.symbol
226
- mt5.symbol_select(symbol, True)
227
- tick = mt5.symbol_info_tick(symbol)
228
- if tick is None:
229
- raise RuntimeError("tick alinamadi: " + symbol)
230
- is_buy = int(pos.type) == int(mt5.POSITION_TYPE_BUY)
231
- req = {
232
- "action": mt5.TRADE_ACTION_DEAL,
233
- "symbol": symbol,
234
- "volume": volume,
235
- "type": mt5.ORDER_TYPE_SELL if is_buy else mt5.ORDER_TYPE_BUY,
236
- "position": ticket,
237
- "price": tick.bid if is_buy else tick.ask,
238
- "deviation": int(p.get("deviation") or 20),
239
- "magic": int(pos.magic or 0),
240
- "comment": "Beast close",
241
- "type_time": mt5.ORDER_TIME_GTC,
242
- "type_filling": mt5.ORDER_FILLING_IOC,
243
- }
244
- return {"result": _send_request(req)}
245
-
246
-
247
- def h_modify(p):
248
- need()
249
- ticket = int(p.get("ticket") or 0)
250
- if not ticket:
251
- raise RuntimeError("ticket zorunlu")
252
- pos = mt5.positions_get(ticket=ticket)
253
- if not pos:
254
- raise RuntimeError("pozisyon bulunamadi: %s" % ticket)
255
- pos = pos[0]
256
- req = {
257
- "action": mt5.TRADE_ACTION_SLTP,
258
- "symbol": pos.symbol,
259
- "position": ticket,
260
- "sl": float(p.get("sl") or 0.0),
261
- "tp": float(p.get("tp") or 0.0),
262
- }
263
- return {"result": _send_request(req)}
264
-
265
-
266
- def h_pending(p):
267
- need()
268
- symbol = str(p.get("symbol") or "").strip().upper()
269
- ptype = str(p.get("type") or "").lower()
270
- volume = float(p.get("volume") or 0)
271
- price = float(p.get("price") or 0)
272
- if not symbol or volume <= 0 or price <= 0:
273
- raise RuntimeError("symbol/volume/price zorunlu")
274
- tmap = {
275
- "buy_limit": mt5.ORDER_TYPE_BUY_LIMIT,
276
- "sell_limit": mt5.ORDER_TYPE_SELL_LIMIT,
277
- "buy_stop": mt5.ORDER_TYPE_BUY_STOP,
278
- "sell_stop": mt5.ORDER_TYPE_SELL_STOP,
279
- }
280
- if ptype not in tmap:
281
- raise RuntimeError("type: buy_limit|sell_limit|buy_stop|sell_stop")
282
- mt5.symbol_select(symbol, True)
283
- req = {
284
- "action": mt5.TRADE_ACTION_PENDING,
285
- "symbol": symbol,
286
- "volume": volume,
287
- "type": tmap[ptype],
288
- "price": price,
289
- "deviation": int(p.get("deviation") or 20),
290
- "magic": int(p.get("magic") or 20260908),
291
- "comment": str(p.get("comment") or "Beast")[:26],
292
- "type_time": mt5.ORDER_TIME_GTC,
293
- "type_filling": mt5.ORDER_FILLING_IOC,
294
- }
295
- if p.get("sl"):
296
- req["sl"] = float(p.get("sl"))
297
- if p.get("tp"):
298
- req["tp"] = float(p.get("tp"))
299
- return {"result": _send_request(req)}
300
-
301
-
302
- def h_cancel(p):
303
- need()
304
- ticket = int(p.get("ticket") or 0)
305
- if not ticket:
306
- raise RuntimeError("ticket zorunlu")
307
- req = {"action": mt5.TRADE_ACTION_REMOVE, "order": ticket}
308
- return {"result": _send_request(req)}
309
-
310
-
311
- def h_rates(p):
312
- """OHLC mumlar: symbol + timeframe (M1..MN1) + count (1..1000)."""
313
- need()
314
- symbol = str(p.get("symbol") or "").strip().upper()
315
- if not symbol:
316
- raise RuntimeError("symbol zorunlu")
317
- tf_name = str(p.get("timeframe") or "M15").strip().upper()
318
- tf_map = {
319
- "M1": mt5.TIMEFRAME_M1, "M2": mt5.TIMEFRAME_M2, "M3": mt5.TIMEFRAME_M3,
320
- "M4": mt5.TIMEFRAME_M4, "M5": mt5.TIMEFRAME_M5, "M6": mt5.TIMEFRAME_M6,
321
- "M10": mt5.TIMEFRAME_M10, "M12": mt5.TIMEFRAME_M12, "M15": mt5.TIMEFRAME_M15,
322
- "M20": mt5.TIMEFRAME_M20, "M30": mt5.TIMEFRAME_M30,
323
- "H1": mt5.TIMEFRAME_H1, "H2": mt5.TIMEFRAME_H2, "H3": mt5.TIMEFRAME_H3,
324
- "H4": mt5.TIMEFRAME_H4, "H6": mt5.TIMEFRAME_H6, "H8": mt5.TIMEFRAME_H8,
325
- "H12": mt5.TIMEFRAME_H12,
326
- "D1": mt5.TIMEFRAME_D1, "W1": mt5.TIMEFRAME_W1, "MN1": mt5.TIMEFRAME_MN1,
327
- }
328
- if tf_name not in tf_map:
329
- raise RuntimeError("timeframe: " + "|".join(tf_map.keys()))
330
- try:
331
- count = int(p.get("count") or 200)
332
- except Exception:
333
- count = 200
334
- count = max(1, min(count, 1000))
335
- mt5.symbol_select(symbol, True)
336
- rates = mt5.copy_rates_from_pos(symbol, tf_map[tf_name], 0, count)
337
- if rates is None:
338
- raise RuntimeError("mum verisi alinamadi: %s %s %s" % (symbol, tf_name, mt5.last_error()))
339
- rows = []
340
- for r in rates:
341
- rows.append({
342
- "time": int(r["time"]),
343
- "open": float(r["open"]),
344
- "high": float(r["high"]),
345
- "low": float(r["low"]),
346
- "close": float(r["close"]),
347
- "tick_volume": int(r["tick_volume"]),
348
- "spread": int(r["spread"]),
349
- "real_volume": int(r["real_volume"]),
350
- })
351
- return {"symbol": symbol, "timeframe": tf_name, "count": len(rows), "rates": rows}
352
-
353
-
354
- def h_margin(p):
355
- """order_calc_margin: tahmini gerekli marj (islem oncesi kalkan icin)."""
356
- need()
357
- symbol = str(p.get("symbol") or "").strip().upper()
358
- side = str(p.get("side") or "buy").lower()
359
- volume = float(p.get("volume") or 0)
360
- if not symbol or volume <= 0 or side not in ("buy", "sell"):
361
- raise RuntimeError("symbol/side/volume zorunlu")
362
- mt5.symbol_select(symbol, True)
363
- price = float(p.get("price") or 0)
364
- if price <= 0:
365
- tick = mt5.symbol_info_tick(symbol)
366
- if tick is None:
367
- raise RuntimeError("tick alinamadi: " + symbol)
368
- price = tick.ask if side == "buy" else tick.bid
369
- order_type = mt5.ORDER_TYPE_BUY if side == "buy" else mt5.ORDER_TYPE_SELL
370
- m = mt5.order_calc_margin(order_type, symbol, volume, price)
371
- return {"margin": (float(m) if m is not None else None), "price": price}
372
-
373
-
374
- def h_all_symbols(p):
375
- """Terminaldeki tum semboller (sembol secici icin). filter: '*XAU*' gibi."""
376
- need()
377
- flt = str(p.get("filter") or "").strip()
378
- if flt:
379
- rows = mt5.symbols_get(group="*" + flt + "*") or []
380
- else:
381
- rows = mt5.symbols_get() or []
382
- cap = 8000
383
- out = []
384
- for r in rows[:cap]:
385
- out.append({
386
- "name": getattr(r, "name", "") or "",
387
- "desc": getattr(r, "description", "") or "",
388
- "visible": bool(getattr(r, "visible", False)),
389
- })
390
- return {"symbols": out, "count": len(rows), "truncated": len(rows) > cap}
391
-
392
-
393
- # ---------------- BeastFinance EA kopru dosyalari ----------------
394
-
395
- def _files_dir():
396
- """MQL5\\Files sandbox klasoru (EA ile ortak). Terminal baglantisi sart."""
397
- need()
398
- dp = ""
399
- try:
400
- ti = mt5.terminal_info()
401
- dp = getattr(ti, "data_path", "") if ti is not None else ""
402
- except Exception:
403
- dp = ""
404
- if not dp:
405
- raise RuntimeError("terminal data_path alinamadi")
406
- d = os.path.join(dp, "MQL5", "Files")
407
- os.makedirs(d, exist_ok=True)
408
- return d
409
-
410
-
411
- def _read_json_file(p):
412
- """EA dosyalari UTF-16 (FILE_UNICODE) ya da UTF-8 olabilir — BOM'a gore coz."""
413
- try:
414
- with open(p, "rb") as f:
415
- buf = f.read()
416
- if not buf:
417
- return None
418
- if buf[:2] in (b"\xff\xfe", b"\xfe\xff"):
419
- raw = buf.decode("utf-16")
420
- elif buf[:3] == b"\xef\xbb\xbf":
421
- raw = buf.decode("utf-8-sig")
422
- else:
423
- try:
424
- raw = buf.decode("utf-8")
425
- except UnicodeDecodeError:
426
- raw = buf.decode("utf-16")
427
- if "\x00" in raw: # BOM'suz UTF-16 (ASCII icerik)
428
- raw = buf.decode("utf-16")
429
- raw = raw.strip()
430
- return json.loads(raw) if raw else None
431
- except Exception:
432
- return None
433
-
434
-
435
- def _write_json_file(p, obj):
436
- """EA tarafi FILE_UNICODE okudugu icin UTF-16 (BOM'lu) yaz."""
437
- with open(p, "wb") as f:
438
- f.write(json.dumps(obj, ensure_ascii=False).encode("utf-16"))
439
-
440
-
441
- def h_ea_status(p):
442
- """Grafikteki BeastFinance EA'nin heartbeat durumu (yuklu mu + izinler)."""
443
- d = _files_dir()
444
- beat = _read_json_file(os.path.join(d, "beast_ea.json"))
445
- ack = _read_json_file(os.path.join(d, "beast_cmd_ack.json"))
446
- note = _read_json_file(os.path.join(d, "beast_note.json"))
447
- if beat is None:
448
- return {"installed": False, "files_dir": d}
449
- return {"installed": True, "files_dir": d, "ea": beat, "last_ack": ack, "note": note}
450
-
451
-
452
- def h_ea_note(p):
453
- """Grafik panosu + seviye cizgileri: beast_note.json yazar (EA bir sonraki
454
- timer turunda okur; screenshot/entegrasyon icin)."""
455
- d = _files_dir()
456
- note = {
457
- "symbol": str(p.get("symbol") or ""),
458
- "text": str(p.get("text") or "")[:4000],
459
- "levels": [],
460
- "at": int(time.time()),
461
- }
462
- lv = p.get("levels")
463
- if isinstance(lv, list):
464
- for x in lv[:20]:
465
- try:
466
- price = float(x.get("price"))
467
- except Exception:
468
- continue
469
- if price > 0:
470
- note["levels"].append({"price": price, "label": str(x.get("label") or "")[:40]})
471
- path = os.path.join(d, "beast_note.json")
472
- _write_json_file(path, note)
473
- return {"ok": True, "path": path, "levels": len(note["levels"])}
474
-
475
-
476
- def h_ea_cmd(p):
477
- """EA'ya komut yaz (ping|chart|status|note) ve ack bekle."""
478
- d = _files_dir()
479
- cmd = str(p.get("cmd") or "").strip()
480
- if not cmd:
481
- raise RuntimeError("cmd gerekli (ping|chart|status|note)")
482
- rid = str(p.get("id") or ("c" + str(int(time.time() * 1000) % 100000000)))
483
- payload = {"id": rid, "cmd": cmd, "params": p.get("params") or {}}
484
- ack_path = os.path.join(d, "beast_cmd_ack.json")
485
- try:
486
- os.remove(ack_path)
487
- except Exception:
488
- pass
489
- with open(os.path.join(d, "beast_cmd.json"), "wb") as f:
490
- f.write(json.dumps(payload, ensure_ascii=False).encode("utf-16"))
491
- timeout = float(p.get("timeoutSec") or 8)
492
- t0 = time.time()
493
- while time.time() - t0 < max(1.0, min(timeout, 30.0)):
494
- time.sleep(0.25)
495
- ack = _read_json_file(ack_path)
496
- if ack and str(ack.get("id") or "") == rid:
497
- return {"ok": True, "ack": ack, "waited": round(time.time() - t0, 2)}
498
- return {"ok": False, "error": "EA yanit vermedi (grafikte BeastFinance yuklu mu?)", "sent": payload}
499
-
500
-
501
- HANDLERS = {
502
- "ping": h_ping,
503
- "policy": h_policy,
504
- "account": h_account,
505
- "terminal": h_terminal,
506
- "symbols": h_symbols,
507
- "all_symbols": h_all_symbols,
508
- "rates": h_rates,
509
- "positions": h_positions,
510
- "orders": h_orders,
511
- "deals": h_deals,
512
- "market": h_market,
513
- "close": h_close,
514
- "modify": h_modify,
515
- "pending": h_pending,
516
- "cancel": h_cancel,
517
- "margin": h_margin,
518
- "ea_status": h_ea_status,
519
- "ea_cmd": h_ea_cmd,
520
- "ea_note": h_ea_note,
521
- }
522
-
523
-
524
- def main():
525
- global TERMINAL_PATH
526
- ap = argparse.ArgumentParser()
527
- ap.add_argument("--terminal", default="")
528
- args, _ = ap.parse_known_args()
529
- TERMINAL_PATH = args.terminal
530
-
531
- for line in sys.stdin:
532
- line = line.strip()
533
- if not line:
534
- continue
535
- try:
536
- req = json.loads(line)
537
- except Exception as e:
538
- out({"id": None, "ok": False, "error": "bozuk json: %s" % e})
539
- continue
540
- rid = req.get("id")
541
- method = str(req.get("method") or "")
542
- params = req.get("params") or {}
543
- fn = HANDLERS.get(method)
544
- if fn is None:
545
- out({"id": rid, "ok": False, "error": "bilinmeyen yontem: " + method})
546
- continue
547
- try:
548
- data = fn(params)
549
- out({"id": rid, "ok": True, "data": data})
550
- except Exception as e:
551
- out({"id": rid, "ok": False, "error": str(e)})
552
-
553
-
554
- if __name__ == "__main__":
555
- if mt5 is None:
556
- out({"event": "bridge", "connected": False, "error": "MetaTrader5 python paketi kurulu degil (pip install MetaTrader5)"})
557
- else:
558
- ok = False
559
- err = ""
560
- try:
561
- if TERMINAL_PATH:
562
- ok = bool(mt5.initialize(path=TERMINAL_PATH))
563
- else:
564
- ok = bool(mt5.initialize())
565
- if not ok:
566
- err = str(mt5.last_error())
567
- except Exception as e:
568
- err = str(e)
569
- acc = None
570
- term = None
571
- if ok:
572
- acc = d(mt5.account_info())
573
- term = d(mt5.terminal_info())
574
- out({"event": "bridge", "connected": ok, "error": "" if ok else err, "account": acc, "terminal": term})
575
- main()
@@ -1,49 +0,0 @@
1
- ---
2
- name: haber-duygu
3
- description: Haber ve piyasa duyarlılığı rehberi — ekonomik takvim riskleri (NFP/CPI/FOMC/faiz), haber öncesi-sonrası pozisyon disiplini, DXY/faiz/VIX/Fear&Greed okuma, risk-on/risk-off ve emtia bağıntıları. Makro/haber ajanı veya trader haber etkisi değerlendirirken ÖNCE bu skill'i okur.
4
- version: 1.0.0
5
- ---
6
-
7
- # Haber & Piyasa Duyarlılığı
8
-
9
- ## TEMEL İLKE
10
-
11
- Haber yön tahmini için değil, **risk zamanlaması** için kullanılır. Yüksek etkili veri saatinde piyasa spreadi genişler ve yön belirsizdir; çoğu zaman en iyi işlem beklemektir.
12
-
13
- ## 1) EKONOMİK TAKVİM
14
-
15
- - Yüksek etkili: FOMC/faiz kararları, NFP (tarım dışı istihdam), CPI/PPI, GDP, işsizlik, ECB/BOE/BOJ kararları, jeopolitik başlıklar.
16
- - Kural: yüksek etkili veriden **15–30 dk önce yeni pozisyon açma**; mevcut pozisyonu gözden geçir (SL sabit, panik kapatma yok).
17
- - Veri sonrası: ilk 5–15 dk fitil/spike olur; kapanış teyidi gelmeden işlem açma.
18
- - Takvimi `web_search`/`deep_search` ile teyit et; tarih/saati yerel saatle yaz (sunucu saati farkını belirt).
19
-
20
- ## 2) DUYGU GÖSTERGELERİ
21
-
22
- - **DXY**: dolar gücü — yükselirse altın ve EURUSD genelde baskılanır (ters korelasyon).
23
- - **ABD 10Y tahvil faizi**: faiz yükseliyorsa risk iştahı azalabilir, altın baskılanabilir.
24
- - **VIX**: yükseliyorsa risk-off; düşüyorsa risk-on.
25
- - **Kripto Fear & Greed**: yalnız BTC/ETH gibi kripto pozisyonlarında; hisse/emtia için ana referans değil.
26
- - Aşırı iyimserlik (greed) ve aşırı korku (fear) uçlarda dönüş riskidir; trend takipçisi için tek başına sinyal değildir.
27
-
28
- ## 3) RİSK-ON / RİSK-OFF
29
-
30
- - Risk-on: hisse ↑, emtia ↑, dolar/altın baskılı olabilir.
31
- - Risk-off: DXY/altın/tahvil ↑, hisse/kripto ↓.
32
- - Makro başlık bölgeyi tersine çevirdiyse mevcut teknik planı **güncelle**, körlemesine uygulama.
33
-
34
- ## 4) HABER DOĞRULAMA
35
-
36
- - Tek kaynağa güvenme; 2+ bağımsız kaynak teyidi ara.
37
- - Manşet ile içerik çelişirse içeriği esas al; tarih/saat eski haberi taze sanma.
38
- - Söylenti (rumor) ve resmi açıklamayı ayır; söylentiye işlem açma.
39
-
40
- ## 5) BAĞINTI NOTLARI
41
-
42
- - XAUUSD ile DXY ters korele; aynı yönde iki korelasyonlu pozisyon açma (bkz. risk-yonetimi).
43
- - Petrol haberleri (OPEC, arz kesintisi) enerji sembollerini ve genel risk iştahını etkiler.
44
- - Emtia sembollerinde broker sembol adını kullan (ör. "GOLD", "XAUUSD" değil) — `mt5_market` ile doğrula.
45
-
46
- ## 6) RAPOR FORMATI
47
-
48
- `Takvim: <saat> <veri> (yüksek) | duygu: risk-on/off | DXY yön | sembol etkisi: <yön/temkin> | aksiyon: bekle/azalt/normal`
49
- Veri saatine 30 dk'dan az varsa bunu raporda AÇIKÇA belirt.