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,154 +0,0 @@
1
- ---
2
- name: mql5
3
- description: MetaTrader 5 tarafında MQL5 (script / indicator / Expert Advisor) yazma-derleme rehberi — mt5_* araçlarının yapamadığı işleri (özel hesap, olay yakalama, EA ile otomatik yürütme, dosya köprüsü) MQL5 ile çözmek gerektiğinde ÖNCE bu skill'i oku. BeastFinance EA (varsayılan, otomatik kurulur) + dosya köprüsü, veri klasörünü bulma, MetaEditor ile derleme ve hazır kod iskeletleri burada.
4
- version: 1.1.0
5
- ---
6
-
7
- # MQL5 Tool Yazma (MetaTrader 5)
8
-
9
- ## NE ZAMAN KULLANILIR
10
-
11
- - `mt5_*` araçları yetmiyorsa: tick/olay anında tepki, çok koşullu emir yönetimi, özel gösterge hesabı, hesap istatistiği, broker'a özel alanlar.
12
- - Beast tarafında tekrarlı bir rutini MQL5 ile terminalin İÇİNDE çalıştırmak gerekiyorsa.
13
- - Basit işi Python/Node ile yapabiliyorsan ÖNCE `python_run` / `run_command` / `mt5_*` dene — MQL5 son çare değil ama en ağır seçenektir.
14
-
15
- ## 1) VERİ KLASÖRÜNÜ BUL (ilk adım)
16
-
17
- 1. `mt5_status` çağır → dönen `terminal.data_path` = MT5 veri klasörü (en güvenilir yol).
18
- 2. Bulamazsan `%APPDATA%\MetaQuotes\Terminal\<hash>\` altındaki klasörlerde `MQL5` dizinini ara; hash'i `origin.txt` içeriğiyle (kurulum yolu) eşleştir.
19
- 3. Klasör düzeni:
20
-
21
- | Klasör | Ne konur |
22
- |---|---|
23
- | `<data_path>\MQL5\Experts\` | Expert Advisor (EA) — chart'a iliştirilir |
24
- | `<data_path>\MQL5\Indicators\` | Özel gösterge |
25
- | `<data_path>\MQL5\Scripts\` | Tek seferlik script — elle bir kez çalıştırılır |
26
- | `<data_path>\MQL5\Include\` | Paylaşılan `.mqh` başlıkları |
27
- | `<data_path>\MQL5\Files\` | MQL5 program sandbox'ı — Beast buradan `read_file` ile okur |
28
-
29
- ## 2) YAZMA
30
-
31
- - Kod `write_file` ile `.mq5` olarak yazılır (UTF-8). `edit_file`, `read_file`, `run_command`, `python_run` yetkilerin açık.
32
- - MQL5 C++ benzeridir; Python paketi yoktur, yalnız MetaTrader standart kütüphanesi vardır.
33
- - Hazır sınıflar: `#include <Trade\Trade.mqh>` (CTrade), `#include <Trade\PositionInfo.mqh>`, `#include <Trade\SymbolInfo.mqh>`.
34
- - Türkçe karakteri yalnız string/yorum içinde kullan; değişken adlarında kullanma.
35
-
36
- ## 3) DERLEME (MetaEditor)
37
-
38
- `metaeditor64.exe`, `terminal64.exe` ile aynı klasördedir (genelde `C:\Program Files\MetaTrader 5\` veya broker kurulum klasörü).
39
-
40
- ```powershell
41
- & "C:\Program Files\MetaTrader 5\metaeditor64.exe" /compile:"<data_path>\MQL5\Scripts\beast_script.mq5" /log:"<data_path>\MQL5\Scripts\beast_script.log"
42
- ```
43
-
44
- - Derleme logu **UTF-16**'dır:
45
- ```powershell
46
- Get-Content -Encoding Unicode "<log>" | Select-String "error|warning"
47
- ```
48
- - "0 errors" görmeden işi bitti sayma. Hata varsa kodu düzelt, yeniden derle.
49
- - Terminalin açık olması derleme için gerekmez; metaeditor yolunu bulamazsan `Get-Command metaeditor64.exe` veya `Get-ChildItem "C:\Program Files" -Recurse -Filter metaeditor64.exe` ile ara.
50
-
51
- ## 4) ÇALIŞTIRMA + BEAST KÖPRÜSÜ
52
-
53
- ### 4.0) BEASTFINANCE EA — VARSAYILAN, OTOMATİK KURULUR (ÖNCE BUNU KULLAN)
54
-
55
- Beast Finance MT5'e bağlandığında sistem bunları otomatik yapar:
56
- - `BeastFinance.mq5`'i `MQL5\Experts\Beast\` altına yazar ve MetaEditor ile derler,
57
- - ilk grafiğe EA'yı ekler (gerçek MT5 formatı: `<expert>` bloğu `<window>` öncesi, `path=Experts\Beast\BeastFinance.ex5`, `expertmode=5`),
58
- - `config\common.ini [Experts]` üzerinden AutoTrading iznini açar.
59
-
60
- Yani MT5 entegrasyonu yazarken EA'yı SIFIRDAN YAZMA, elle iliştirme varsayma — köprü ZATEN kurulu:
61
-
62
- | Dosya (MQL5\Files) | Yön | İçerik |
63
- |---|---|---|
64
- | `beast_ea.json` | EA → Beast | heartbeat: version, symbol, period, equity/balance, `terminal_trade_allowed`, `mql_trade_allowed`, positions, note |
65
- | `beast_cmd.json` | Beast → EA | komut: `{id, cmd, params}` — desteklenen: ping / chart / status / note / shot |
66
- | `beast_cmd_ack.json` | EA → Beast | komut sonucu: `{ok, id, cmd, result|error}` |
67
- | `beast_note.json` | Beast → EA | grafik panosu: `{symbol?, text, levels:[{price,label}]}` — pano + yatay çizgiler; screenshot'ta görünür |
68
-
69
- - GRAFİK GÖRÜNTÜSÜ: `shot` komutu `{file, width, height, symbol?, timeframe?, template?}` alır — ChartScreenShot ile GERÇEK PNG üretir. Aktif grafik istenen sembol/periyot ile aynıysa panoyu + seviye çizgilerini içerir; farklıysa EA `ChartOpen` + `BeastShot.tpl` (açık tema, EA bloğu yok) ile geçici grafik açıp kapatır. Bu komutu sarmalayan VARSAYILAN araç `tool__mt5_shot`'tır: PNG'yi çağıran ajana görsel olarak enjekte eder, `path` döndürür (send_file / agent_dm image ile paylaşılır). Seviyeleri grafikte göstermek için önce `mt5_ea note`, sonra `tool__mt5_shot` çağır — paralel ekipte teknik ajan seviyeleri çizer, görsel ajan screenshot ile teyit edip trader'a atar.
70
-
71
- - Finance oturumlarındaki ajan aracı: `mt5_ea` (action: status|ping|chart|note); grafik PNG'si için varsayılan `tool__mt5_shot` (tüm oturumlarda açık).
72
- - Yeni MT5 entegrasyonu gerekiyorsa ÖNCE bu köprüyü GENİŞLET: EA'da `ProcessCommands()` içine yeni komut + Beast tarafında `mt5_ea` / python `ea_cmd`. Sıfırdan EA yazma.
73
- - EA kaynağı Beast uygulamasında `src/agent/mt5/BeastFinance.mq5`; güncelleme oradan yapılır, setup yeniden derler.
74
- - Derleme hatalarında dosya kodlaması UTF-16 (`FILE_UNICODE`) kullanılır; MQL5'te `FILE_UTF8` yoktur.
75
-
76
- ### 4.1) Elle script/EA çalıştırma
77
-
78
- - **Script**: MT5 → Navigator → Scripts → çift tık (kullanıcı) — Python API'den MQL5 tetiklenemez.
79
- - **EA**: chart'a iliştirilir; AutoTrading düğmesi açık olmalıdır.
80
- - **Dosya köprüsü (önerilen)**:
81
- - MQL5 → Beast: program `MQL5\Files\beast_signal.json` yazar; ajan `read_file` ile `<data_path>\MQL5\Files\beast_signal.json` okur.
82
- - Beast → MQL5: ajan `beast_cmd.json` yazar; EA `FileRead` ile komutu çeker (polling).
83
- - Kullanıcıya EA/script'i nasıl iliştireceğini net söyle; "otomatik çalışıyor" varsayma.
84
-
85
- ## 5) KOD İSKELETLERİ
86
-
87
- ### Script → dosyaya veri yaz (Beast okur)
88
-
89
- ```mql5
90
- #property version "1.00"
91
- #property script_show_inputs
92
- input string OutFile = "beast_signal.json";
93
-
94
- void OnStart()
95
- {
96
- double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
97
- double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
98
- int h = FileOpen(OutFile, FILE_WRITE | FILE_TXT | FILE_ANSI);
99
- if(h == INVALID_HANDLE)
100
- {
101
- Print("dosya acilamadi: ", GetLastError());
102
- return;
103
- }
104
- FileWriteString(h, StringFormat("{\"symbol\":\"%s\",\"bid\":%.5f,\"ask\":%.5f,\"time\":\"%s\"}",
105
- _Symbol, bid, ask, TimeToString(TimeCurrent(), TIME_DATE | TIME_SECONDS)));
106
- FileClose(h);
107
- Print("beast_signal yazildi: ", bid, " / ", ask);
108
- }
109
- ```
110
-
111
- ### EA iskeleti (CTrade)
112
-
113
- ```mql5
114
- #property version "1.00"
115
- #include <Trade\Trade.mqh>
116
- CTrade trade;
117
-
118
- int OnInit()
119
- {
120
- trade.SetExpertMagicNumber(20260910);
121
- return INIT_SUCCEEDED;
122
- }
123
-
124
- void OnTick()
125
- {
126
- /* sinyal + risk: lot hesabı, SL/TP zorunlu; martingale YOK */
127
- /* trade.Buy(lot, _Symbol, 0.0, sl, tp, "beast"); */
128
- }
129
-
130
- void OnDeinit(const int reason) {}
131
- ```
132
-
133
- ### Ters yön: komut dosyası oku
134
-
135
- ```mql5
136
- bool ReadCmd(string &out)
137
- {
138
- if(!FileIsExist("beast_cmd.json")) return false;
139
- int h = FileOpen("beast_cmd.json", FILE_READ | FILE_TXT | FILE_ANSI);
140
- if(h == INVALID_HANDLE) return false;
141
- out = FileReadString(h);
142
- FileClose(h);
143
- return true;
144
- }
145
- ```
146
-
147
- ## 6) KURALLAR
148
-
149
- - SL'siz işlem/EA yazma; martingale/kademeli lot artışı YASAK.
150
- - Sembol adını `mt5_market` ile doğrula — broker'da neyse o (örn "GOLD", "XAUUSD" değil).
151
- - `TimeCurrent()` broker sunucu saatidir; raporda saat dilimini belirt.
152
- - Ağ/DLL kullanacaksan kullanıcıdan onay iste (`#import` varsayılan kapalıdır).
153
- - Şifre/API anahtarını koda, loga, rapora YAZMA.
154
- - Derlenmemiş/çalıştırılmamış kodu "bitti" diye raporlama; kullanıcıya çalıştırma adımını açıkça söyle.
@@ -1,60 +0,0 @@
1
- ---
2
- name: price-action
3
- description: Fiyat yapısı / price action analiz rehberi — market structure (HH/LL, BOS, CHoCH), destek-direnç bölgeleri, likidite süpürme, çoklu zaman dilimi teyidi, giriş/SL/TP yerleşimi. Teknik analiz ajanı veya trader bir sembolde yön/giriş kararı verirken ÖNCE bu skill'i okur.
4
- version: 1.0.0
5
- ---
6
-
7
- # Price Action / Fiyat Yapısı
8
-
9
- ## TEMEL İLKE
10
-
11
- Yön kararı YAPIDAN gelir, göstergeden değil. MA kesişimi tek başına gürültüdür; teyit yoksa işlem yok.
12
-
13
- ## 1) MARKET STRUCTURE (önce bu)
14
-
15
- - Swing high / swing low'ları işaretle (lookback: son 50-100 mum yeterli).
16
- - Yükseliş yapısı: **HH + HL** (higher high, higher low). Düşüş: **LH + LL**.
17
- - **BOS (Break of Structure)**: trend yönündeki son swing seviyesinin kapanışla kırılması = trend devam teyidi.
18
- - **CHoCH (Change of Character)**: karşı yöndeki ilk yapı kırılması = olası dönüş sinyali; BOS ile karıştırma.
19
- - Yapı belirsizse (range) → BEKLE; range'de sadece sınırlardan işlem düşünülür.
20
-
21
- ## 2) DESTEK / DİRENÇ + LİKİDİTE
22
-
23
- - Bölgeyi çizgi değil **alan** olarak al (mum gövdeleri + fitiller).
24
- - Önem sırası: HTF (H4/D1) > LTF (M15/M5). HTF seviyesi LTF'de daha güçlüdür.
25
- - Eşit tepeler/dipler likidite havuzudur; fitil ile "süpürülme" (stop hunt) sık olur — kırılımda **kapanış teyidi** ara.
26
- - Yuvarlak rakamlar (2400, 1.1000) ve önceki günün high/low'u doğal seviyedir.
27
-
28
- ## 3) ÇOKLU ZAMAN DİLİMİ (MTF)
29
-
30
- 1. HTF (H4/D1): yön ve ana bölge.
31
- 2. MTF (H1/M15): yapı + BOS/CHoCH.
32
- 3. LTF (M5/M1): giriş tetiği (retest, engulfing, iğne).
33
- Kural: LTF sinyali HTF yönüne tersse işlem açma.
34
-
35
- ## 4) MOMENTUM / VOLATİLİTE
36
-
37
- - ATR: SL mesafesi ve pozisyon boyutu için (sabit pip değil, ATR bazlı).
38
- - RSI divergence sadece **teyit** olarak kullanılır; tek başına giriş sebebi değildir.
39
- - Hacim/range daralması sıkışma (squeeze) → kırılım yaklaşıyor; yön teyidi bekle.
40
-
41
- ## 5) GİRİŞ / SL / TP
42
-
43
- - Giriş: BOS sonrası geri çekilme (pullback) + retest teyidi; kovalama yok.
44
- - SL: yapının arkasına (son swing low/high'ın ötesi) + spread/ATR payı. Yapının İÇİNE SL koyma.
45
- - Geniş SL tercih ediliyorsa: ~4×ATR SL, ~2×ATR'de BE (break-even) taşıma.
46
- - TP: bir sonraki HTF bölgesi. R:R ESNEKTİR — scalp/hızlı işlemlerde TP 0.3R–0.5R olabilir; R:R ≥ 1.5 ŞART DEĞİL. Kısmi kâr alımı serbest ve teşvik edilir: 0.3-0.5R'de pozisyonun bir kısmını realize et, kalanı korumalı trailing ile taşı.
47
- - KÂR KORUMA: +0.3R'de sistem SL'yi kilitler (en iyi kârın 0.15R gerisi); kârın eksiye dönmesine izin verme — gerekiyorsa 0.3-0.5R'de kısmi TP ile kârı cebe al.
48
- - BE'e çekmeden SL'siz/işlemsiz kalma; her pozisyonun SL'si olsun.
49
-
50
- ## 6) YASAKLAR
51
-
52
- - Teyitsiz (BOS/CHoCH olmadan) giriş.
53
- - Zarara ekleme (averaging down) ve martingale.
54
- - Haber anında spread genişken piyasa emri (bkz. haber-duygu skill'i).
55
- - Yapıya ters, sırf "ucuz/pahalı" diye işlem.
56
-
57
- ## 7) RAPOR FORMATI
58
-
59
- Tek satır: `SEMBOL | yön | giriş | SL | TP | yapı gerekçesi (BOS/CHoCH/bölge) | R:R`
60
- Belirsizse net yaz: `BEKLE: <sebep>`.
@@ -1,52 +0,0 @@
1
- ---
2
- name: risk-yonetimi
3
- description: Pozisyon boyutlandırma ve risk disiplini rehberi — hesap yüzdesiyle lot hesabı, marj/kaldıraç denetimi, max eşzamanlı pozisyon, korelasyon/tek yön birikme, günlük kayıp limiti, SL/BE/trailing kuralları. Risk ajanı veya trader her turda ve her işlemden önce bu skill'e göre kontrol yapar.
4
- version: 1.0.0
5
- ---
6
-
7
- # Risk Yönetimi
8
-
9
- ## TEMEL KURAL
10
-
11
- Önce kaybı sınırla, kârı piyasa versin. İşlem başına risk sabittir; lot, SL mesafesine göre hesaplanır.
12
-
13
- ## 1) POZİSYON BOYUTU
14
-
15
- - İşlem başına risk: hesabın **%0.5–1'i** (agresif değilse %0.25–0.5).
16
- - Lot hesabı: `lot = (bakiye × risk%) / (SL_mesafesi × sembolün pip değeri)`.
17
- - SL mesafesi ATR/yapıdan gelir; önce SL belirle, sonra lotu küçült — tersini yapma.
18
- - Broker limitleri: panel `max lot` ve `max eşzamanlı pozisyon` ayarlarına uy; sistem reddederse zorlama.
19
-
20
- ## 2) MARJ / KALDIRAÇ
21
-
22
- - Serbest marjın tamamını tek işleme bağlama; toplam açık risk serbest marjın küçük bir kısmı olsun.
23
- - Kaldıraç yüksekse lotu düşür; kaldıraç = risk değil, imkândır.
24
- - Marj seviyesi düşerken yeni pozisyon AÇMA; önce riski azalt.
25
-
26
- ## 3) PORTFÖY DENETİMİ (her turda)
27
-
28
- - Açık pozisyonların toplam riskini hesapla (SL'lere göre kayıp potansiyeli).
29
- - **Tek yön birikme**: aynı yönde üst üste pozisyon = tek işlem gibi davranır; toplam riski tek işlem limiti gibi say.
30
- - **Korelasyon**: XAUUSD/EURUSD ile DXY ters koreledir; aynı yönde iki korelasyonlu pozisyon riski katlar.
31
- - SL'siz pozisyon varsa ilk iş: SL tamamla veya kapat.
32
- - Hedefine ulaşan/kâra geçen pozisyonda BE veya kısmi kâr; trailing ATR bazlı.
33
- - **Kâr koruma:** +0.3R'de sistem SL'yi en iyi kârın 0.15R gerisine kilitler; +0.3-0.5R'de kısmi TP (ör. %50) ile kârı cebe al, kalanı trailing'e bırak. TP için R:R ≥ 1.5 şartı YOK — hızlı kâr toplama (scalp) serbest; ama kârı kale verme.
34
- - **Sembol bazlı öğrenme (seçici):** her kapanışa ders YAZMA — yalnız gerçekten öğretici, tekrar kullanılabilir içgörüyü TEK kısa cümleyle (≈20 kelime) mt5_ogrenme add ile kaydet; yeni işlem öncesi o sembolün stats/list geçmişini oku — aynı hatayı tekrarlama.
35
-
36
- ## 4) KAYIP LİMİTLERİ
37
-
38
- - Günlük kayıp limiti belirle (ör. hesabın %2–3'ü). Limit dolduysa **o gün yeni işlem yok**; raporla.
39
- - Üst üste 2-3 kayıptan sonra lotu artırma (revenge trade YASAK); aksine küçült veya dur.
40
- - Drawdown artıyorsa tur sıklığını/agresifliği azalt, sadece A+ setuplara gir.
41
-
42
- ## 5) YASAKLAR
43
-
44
- - Martingale / kademeli lot artışı.
45
- - SL taşımayı kaybı büyütecek yönde yapmak (SL genişletme).
46
- - Marjı zorlayan "son işlem" kumarı.
47
- - Aynı anda korelasyonlu 3+ pozisyonla tek yön yığmak.
48
-
49
- ## 6) RAPOR FORMATI
50
-
51
- `Risk: toplam açık R%X | marj kullanımı %Y | en riskli pozisyon: ... | öneri: SL/BE/küçült/kapat`
52
- Sınır aşımı varsa öncelikli ve net yaz.
package/src/mt5bridge.js DELETED
@@ -1,215 +0,0 @@
1
- 'use strict';
2
-
3
- /* Beast Finance — MT5 köprü yöneticisi (main süreç).
4
- Python stdio köprüsünü (mt5_bridge.py) spawn eder; JSON satır istek/yanıt
5
- ve event akışını yönetir. Python bulunamazsa aday listesinde sıradakini
6
- dener; süreç düşerse backoff ile yeniden başlatır. */
7
-
8
- const { spawn } = require('child_process');
9
- const path = require('path');
10
- const fs = require('fs');
11
- const { EventEmitter } = require('events');
12
-
13
- const BUNDLED_SCRIPT = path.join(__dirname, 'agent', 'scripts', 'mt5_bridge.py');
14
-
15
- /* Paketli uygulamada köprü scripti app.asar İÇİNDE kalır — harici Python
16
- onu OKUYAMAZ. Her başlatmada %APPDATA%\beast\finance altına güncel haliyle
17
- yazılır (Node asar içini okuyabilir) ve oradan çalıştırılır. */
18
- function scriptPath() {
19
- try {
20
- const dest = path.join(process.env.APPDATA || process.env.TMP || process.cwd(), 'beast', 'finance', 'mt5_bridge.py');
21
- fs.mkdirSync(path.dirname(dest), { recursive: true });
22
- fs.copyFileSync(BUNDLED_SCRIPT, dest);
23
- return dest;
24
- } catch {
25
- return BUNDLED_SCRIPT;
26
- }
27
- }
28
-
29
- class MT5Bridge extends EventEmitter {
30
- constructor() {
31
- super();
32
- this.proc = null;
33
- this._buf = '';
34
- this._reqId = 1;
35
- this._pending = new Map();
36
- this._stopped = true;
37
- this._backoff = 1500;
38
- this._lastError = '';
39
- this._terminal = null;
40
- this._account = null;
41
- this._candidates = ['python', 'py -3'];
42
- this._candIdx = 0;
43
- this._terminalPath = '';
44
- this._everConnected = false;
45
- }
46
-
47
- get running() {
48
- return !!this.proc;
49
- }
50
-
51
- status() {
52
- return {
53
- running: this.running,
54
- connected: !!this._terminal,
55
- terminal: this._terminal,
56
- account: this._account,
57
- error: this._lastError,
58
- python: this._candidates[this._candIdx] || '',
59
- };
60
- }
61
-
62
- /* opts: { candidates: ['python','py -3'], terminal: 'C:\\...\\terminal64.exe' } */
63
- start(opts = {}) {
64
- if (Array.isArray(opts.candidates) && opts.candidates.length) {
65
- const next = opts.candidates.map((c) => String(c).trim()).filter(Boolean);
66
- if (next.join('|') !== this._candidates.join('|')) {
67
- this._candidates = next;
68
- this._candIdx = 0;
69
- }
70
- }
71
- this._terminalPath = String(opts.terminal || '').trim();
72
- this._stopped = false;
73
- if (this.running) return;
74
- this._spawn();
75
- }
76
-
77
- _spawn() {
78
- if (this._stopped) return;
79
- const cand = this._candidates[this._candIdx] || 'python';
80
- /* 'py -3' gibi çok kelimeli kısa komutlar bölünür; tam yol tek exe'dir */
81
- const parts = /[\\/]/.test(cand) ? [cand] : cand.split(/\s+/);
82
- const exe = parts[0];
83
- const preArgs = parts.slice(1);
84
- let proc;
85
- try {
86
- proc = spawn(exe, [...preArgs, scriptPath(), ...(this._terminalPath ? ['--terminal', this._terminalPath] : [])], {
87
- stdio: ['pipe', 'pipe', 'pipe'],
88
- windowsHide: true,
89
- });
90
- } catch (e) {
91
- this._lastError = 'Python başlatılamadı: ' + String((e && e.message) || e);
92
- this.emit('log', { level: 'error', line: this._lastError });
93
- this._nextCandidateOrRetry();
94
- return;
95
- }
96
- this.proc = proc;
97
- this._buf = '';
98
- proc.stdout.setEncoding('utf8');
99
- proc.stdout.on('data', (chunk) => {
100
- this._buf += chunk;
101
- let i;
102
- while ((i = this._buf.indexOf('\n')) >= 0) {
103
- const line = this._buf.slice(0, i).trim();
104
- this._buf = this._buf.slice(i + 1);
105
- if (line) this._onLine(line);
106
- }
107
- });
108
- proc.stderr.setEncoding('utf8');
109
- proc.stderr.on('data', (c) => {
110
- const t = String(c).trim();
111
- if (t) this.emit('log', { level: 'error', line: t.slice(0, 400) });
112
- });
113
- proc.on('error', (e) => {
114
- this._lastError = `Python (${exe}) bulunamadı/başlatılamadı: ` + String((e && e.message) || e);
115
- this.emit('log', { level: 'error', line: this._lastError });
116
- try { this._failAll(this._lastError); } catch {}
117
- if (this.proc === proc) this.proc = null;
118
- this._nextCandidateOrRetry();
119
- });
120
- proc.on('exit', (code) => {
121
- if (this.proc === proc) this.proc = null;
122
- this._terminal = null;
123
- this._account = null;
124
- try { this._failAll('MT5 köprüsü kapandı (kod ' + code + ')'); } catch {}
125
- this.emit('bridge', { connected: false, error: this._lastError || ('süreç kapandı (kod ' + code + ')') });
126
- this._nextCandidateOrRetry();
127
- });
128
- }
129
-
130
- /* aday python'ları sırayla dener; hepsi tükendiyse backoff ile yeniden dener */
131
- _nextCandidateOrRetry() {
132
- if (this._stopped) return;
133
- if (this._candIdx < this._candidates.length - 1) {
134
- this._candIdx += 1;
135
- this.emit('log', { level: 'info', line: 'python adayı deneniyor: ' + this._candidates[this._candIdx] });
136
- setTimeout(() => { try { this._spawn(); } catch {} }, 300);
137
- return;
138
- }
139
- this._candIdx = 0;
140
- setTimeout(() => { try { if (!this._stopped && !this.running) this._spawn(); } catch {} }, this._backoff);
141
- this._backoff = Math.min(this._backoff * 2, 15000);
142
- }
143
-
144
- _onLine(line) {
145
- let msg;
146
- try { msg = JSON.parse(line); } catch {
147
- this.emit('log', { level: 'info', line: line.slice(0, 240) });
148
- return;
149
- }
150
- if (msg.event) {
151
- if (msg.event === 'bridge') {
152
- this._terminal = msg.terminal || null;
153
- this._account = msg.account || null;
154
- this._lastError = String(msg.error || '');
155
- if (msg.connected) {
156
- this._everConnected = true;
157
- this._backoff = 1500;
158
- }
159
- this.emit('bridge', msg);
160
- } else if (msg.event === 'log') {
161
- this.emit('log', msg);
162
- } else {
163
- this.emit('event', msg);
164
- }
165
- return;
166
- }
167
- if (msg.id != null && this._pending.has(msg.id)) {
168
- const en = this._pending.get(msg.id);
169
- this._pending.delete(msg.id);
170
- clearTimeout(en.timer);
171
- en.resolve(msg);
172
- }
173
- }
174
-
175
- call(method, params, timeoutMs = 12000) {
176
- if (!this.running) return Promise.resolve({ ok: false, error: 'MT5 köprüsü çalışmıyor' });
177
- const id = this._reqId++;
178
- let resolveFn = null;
179
- const p = new Promise((resolve) => { resolveFn = resolve; });
180
- const timer = setTimeout(() => {
181
- this._pending.delete(id);
182
- resolveFn({ ok: false, error: 'MT5 zaman aşımı: ' + method });
183
- }, Math.max(2000, Number(timeoutMs) || 12000));
184
- this._pending.set(id, { timer, resolve: resolveFn });
185
- try {
186
- this.proc.stdin.write(JSON.stringify({ id, method, params: params || {} }) + '\n');
187
- } catch (e) {
188
- clearTimeout(timer);
189
- this._pending.delete(id);
190
- resolveFn({ ok: false, error: 'köprü yazma hatası: ' + String((e && e.message) || e) });
191
- }
192
- return p;
193
- }
194
-
195
- stop() {
196
- this._stopped = true;
197
- try { this._failAll('köprü kapatıldı'); } catch {}
198
- if (this.proc) {
199
- try { this.proc.kill(); } catch {}
200
- this.proc = null;
201
- }
202
- this._terminal = null;
203
- this._account = null;
204
- }
205
-
206
- _failAll(err) {
207
- for (const [, en] of this._pending) {
208
- clearTimeout(en.timer);
209
- en.resolve({ ok: false, error: err });
210
- }
211
- this._pending.clear();
212
- }
213
- }
214
-
215
- module.exports = new MT5Bridge();