beast-agent 2.76.6 → 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.
- package/package.json +1 -1
- package/src/agent/bots.js +669 -664
- package/src/agent/customtools.js +6 -19
- package/src/agent/engine.js +55 -307
- package/src/agent/seeds/tool-yazma/SKILL.md +13 -16
- package/src/agent/skills.js +14 -35
- package/src/agent/supertonic.js +622 -0
- package/src/agent/tools.js +3 -7
- package/src/main.js +77 -6164
- package/src/preload.js +2 -18
- package/src/renderer/i18n.js +14 -8
- package/src/renderer/index.html +0 -297
- package/src/renderer/renderer.js +142 -2301
- package/src/renderer/style.css +3 -825
- package/src/agent/defaulttools/mt5_barlar2/run.js +0 -188
- package/src/agent/defaulttools/mt5_barlar2/tool.json +0 -23
- package/src/agent/defaulttools/mt5_bekleyen/run.js +0 -105
- package/src/agent/defaulttools/mt5_bekleyen/tool.json +0 -18
- package/src/agent/defaulttools/mt5_durum/run.js +0 -93
- package/src/agent/defaulttools/mt5_durum/tool.json +0 -10
- package/src/agent/defaulttools/mt5_emir/run.js +0 -98
- package/src/agent/defaulttools/mt5_emir/tool.json +0 -17
- package/src/agent/defaulttools/mt5_emir_iptal/run.js +0 -90
- package/src/agent/defaulttools/mt5_emir_iptal/tool.json +0 -12
- package/src/agent/defaulttools/mt5_fiyat/run.js +0 -87
- package/src/agent/defaulttools/mt5_fiyat/tool.json +0 -16
- package/src/agent/defaulttools/mt5_gecmis/run.js +0 -87
- package/src/agent/defaulttools/mt5_gecmis/tool.json +0 -12
- package/src/agent/defaulttools/mt5_kapat/run.js +0 -108
- package/src/agent/defaulttools/mt5_kapat/tool.json +0 -15
- package/src/agent/defaulttools/mt5_m15_m5/m15m5.py +0 -60
- package/src/agent/defaulttools/mt5_m15_m5/run.js +0 -73
- package/src/agent/defaulttools/mt5_m15_m5/tool.json +0 -10
- package/src/agent/defaulttools/mt5_pozisyon_gecmis/run.js +0 -144
- package/src/agent/defaulttools/mt5_pozisyon_gecmis/tool.json +0 -12
- package/src/agent/defaulttools/mt5_shot/run.js +0 -649
- package/src/agent/defaulttools/mt5_shot/stitch.js +0 -151
- package/src/agent/defaulttools/mt5_shot/tool.json +0 -25
- package/src/agent/defaulttools/mt5_sltp/run.js +0 -92
- package/src/agent/defaulttools/mt5_sltp/tool.json +0 -14
- package/src/agent/financetools.js +0 -1025
- package/src/agent/finindicators.js +0 -254
- package/src/agent/finrisk.js +0 -289
- package/src/agent/finstats.js +0 -239
- package/src/agent/finwatch.js +0 -302
- package/src/agent/mt5/BeastFinance.mq5 +0 -498
- package/src/agent/mt5/BeastShot.tpl +0 -0
- package/src/agent/mt5setup.js +0 -542
- package/src/agent/scripts/mt5_bridge.py +0 -575
- package/src/agent/seeds/haber-duygu/SKILL.md +0 -49
- package/src/agent/seeds/mql5/SKILL.md +0 -154
- package/src/agent/seeds/price-action/SKILL.md +0 -60
- package/src/agent/seeds/risk-yonetimi/SKILL.md +0 -52
- package/src/mt5bridge.js +0 -215
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
// MT5 CANLI FİYAT — stdin: JSON args · stdout: JSON sonuç
|
|
3
|
-
const { spawn } = require('child_process');
|
|
4
|
-
const fs = require('fs');
|
|
5
|
-
const path = require('path');
|
|
6
|
-
|
|
7
|
-
/* TAŞINABİLİR YOL ÇÖZÜMÜ: Beast gömülü python → sistem python'ları → PATH.
|
|
8
|
-
Köprü dosyası %APPDATA%\beast\finance\mt5_bridge.py'den (veya BEAST_FINANCE_DIR)
|
|
9
|
-
okunur; ortam değişkenleriyle geçersiz kılınabilir. */
|
|
10
|
-
function resolvePython() {
|
|
11
|
-
const cands = [];
|
|
12
|
-
if (process.env.BEAST_PYTHON) cands.push({ exe: String(process.env.BEAST_PYTHON), args: [] });
|
|
13
|
-
if (process.env.APPDATA) cands.push({ exe: path.join(process.env.APPDATA, 'beast', 'py', 'python.exe'), args: [] });
|
|
14
|
-
for (const v of ['314', '313', '312', '311', '310']) cands.push({ exe: 'C:\\Python' + v + '\\python.exe', args: [] });
|
|
15
|
-
cands.push({ exe: 'python', args: [] }, { exe: 'py', args: ['-3'] });
|
|
16
|
-
for (const c of cands) {
|
|
17
|
-
if (c.exe === 'python' || c.exe === 'py') return c;
|
|
18
|
-
try { if (fs.existsSync(c.exe)) return c; } catch (e) {}
|
|
19
|
-
}
|
|
20
|
-
return { exe: 'python', args: [] };
|
|
21
|
-
}
|
|
22
|
-
function resolveBridge() {
|
|
23
|
-
const cands = [];
|
|
24
|
-
if (process.env.BEAST_BRIDGE) cands.push(String(process.env.BEAST_BRIDGE));
|
|
25
|
-
if (process.env.BEAST_FINANCE_DIR) cands.push(path.join(String(process.env.BEAST_FINANCE_DIR), 'mt5_bridge.py'));
|
|
26
|
-
if (process.env.APPDATA) cands.push(path.join(process.env.APPDATA, 'beast', 'finance', 'mt5_bridge.py'));
|
|
27
|
-
for (const p of cands) { try { if (p && fs.existsSync(p)) return p; } catch (e) {} }
|
|
28
|
-
return cands[0] || '';
|
|
29
|
-
}
|
|
30
|
-
const PYSPEC = resolvePython();
|
|
31
|
-
const PY = PYSPEC.exe;
|
|
32
|
-
const PY_ARGS = PYSPEC.args;
|
|
33
|
-
const BRIDGE = resolveBridge();
|
|
34
|
-
|
|
35
|
-
const TIMEOUT = 35000;
|
|
36
|
-
|
|
37
|
-
function call(requests) {
|
|
38
|
-
return new Promise((resolve) => {
|
|
39
|
-
let py;
|
|
40
|
-
try { py = spawn(PY, [...PY_ARGS, BRIDGE], { windowsHide: true, stdio: ['pipe', 'pipe', 'pipe'] }); }
|
|
41
|
-
catch (e) { return resolve({ ok: false, error: 'python baslatilamadi: ' + e.message }); }
|
|
42
|
-
const results = {};
|
|
43
|
-
let buf = '';
|
|
44
|
-
let errTail = '';
|
|
45
|
-
let settled = false;
|
|
46
|
-
const finish = (obj) => { if (!settled) { settled = true; clearTimeout(timer); try { py.kill(); } catch (e) {} resolve(obj); } };
|
|
47
|
-
const timer = setTimeout(() => finish({ ok: false, error: 'zaman asimi: MT5 terminali acik ve yanit veriyor mu?' }), TIMEOUT);
|
|
48
|
-
py.stdout.on('data', (d) => {
|
|
49
|
-
buf += d.toString('utf8');
|
|
50
|
-
let i;
|
|
51
|
-
while ((i = buf.indexOf('\n')) >= 0) {
|
|
52
|
-
const line = buf.slice(0, i).trim(); buf = buf.slice(i + 1);
|
|
53
|
-
if (!line) continue;
|
|
54
|
-
let o = null;
|
|
55
|
-
try { o = JSON.parse(line); } catch (e) { continue; }
|
|
56
|
-
if (o && o.event) continue;
|
|
57
|
-
if (o && typeof o.id === 'number' && Object.prototype.hasOwnProperty.call(o, 'ok')) {
|
|
58
|
-
results[o.id] = o;
|
|
59
|
-
if (Object.keys(results).length >= requests.length) {
|
|
60
|
-
const arr = requests.map((_, k) => results[k + 1]);
|
|
61
|
-
finish(arr.length === 1 ? arr[0] : { ok: true, results: arr });
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
py.stderr.on('data', (d) => { errTail = (errTail + d.toString('utf8')).slice(-800); });
|
|
67
|
-
py.on('error', (e) => finish({ ok: false, error: 'python baslatilamadi: ' + e.message }));
|
|
68
|
-
py.on('close', (code) => { if (Object.keys(results).length < requests.length) finish({ ok: false, error: 'bridge erken cikti code=' + code + ' ' + errTail }); });
|
|
69
|
-
requests.forEach((r, k) => py.stdin.write(JSON.stringify({ id: k + 1, method: r.method, params: r.params || {} }) + '\n'));
|
|
70
|
-
py.stdin.end();
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
(async function main() {
|
|
75
|
-
let args = {};
|
|
76
|
-
try { args = JSON.parse(fs.readFileSync(0, 'utf8') || '{}'); } catch (e) {}
|
|
77
|
-
let syms = args.symbols;
|
|
78
|
-
if (typeof syms === 'string') syms = [syms];
|
|
79
|
-
if (!Array.isArray(syms) || syms.length === 0) return console.log(JSON.stringify({ ok: false, error: 'symbols dizisi zorunlu, orn [\"XAUUSD\"]' }));
|
|
80
|
-
const r = await call([{ method: 'symbols', params: { symbols: syms } }]);
|
|
81
|
-
if (r.ok && r.data) return console.log(JSON.stringify({ ok: true, symbols: r.data.symbols }));
|
|
82
|
-
console.log(JSON.stringify({ ok: false, error: r.error || 'fiyat alinamadi' }));
|
|
83
|
-
})();
|
|
84
|
-
|
|
85
|
-
/* PATCH 2026-09-10b: electron app-mode cocuk prosesi kapanmiyordu (90sn timeout).
|
|
86
|
-
stdout'un boruya bosalmasi icin kisa bekleme, sonra zorla cik. */
|
|
87
|
-
setTimeout(() => process.exit(0), 1500);
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "mt5_fiyat",
|
|
3
|
-
"description": "MT5 canlı fiyat okur: symbols dizisindeki her sembol için bid/ask/spread/digit + sembol bilgisi döner. Broker sembol adlari GOLD ve BITCOIN'dir (XAUUSD/BTCUSD degil — onlar missing doner). Eksik sembol 'missing' işaretlenir. Örn: {\"symbols\":[\"GOLD\",\"BITCOIN\"]}",
|
|
4
|
-
"parameters": {
|
|
5
|
-
"type": "object",
|
|
6
|
-
"properties": {
|
|
7
|
-
"symbols": {
|
|
8
|
-
"type": "array",
|
|
9
|
-
"items": { "type": "string" },
|
|
10
|
-
"description": "Sorgulanacak semboller, örn XAUUSD, BTCUSD"
|
|
11
|
-
}
|
|
12
|
-
},
|
|
13
|
-
"required": ["symbols"]
|
|
14
|
-
},
|
|
15
|
-
"updatedAt": "2026-09-09T18:45:00.000Z"
|
|
16
|
-
}
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
// MT5 KAPANMIS ISLEM GECMISI — stdin: JSON args · stdout: JSON sonuç
|
|
3
|
-
const { spawn } = require('child_process');
|
|
4
|
-
const fs = require('fs');
|
|
5
|
-
const path = require('path');
|
|
6
|
-
|
|
7
|
-
/* TAŞINABİLİR YOL ÇÖZÜMÜ: Beast gömülü python → sistem python'ları → PATH.
|
|
8
|
-
Köprü dosyası %APPDATA%\beast\finance\mt5_bridge.py'den (veya BEAST_FINANCE_DIR)
|
|
9
|
-
okunur; ortam değişkenleriyle geçersiz kılınabilir. */
|
|
10
|
-
function resolvePython() {
|
|
11
|
-
const cands = [];
|
|
12
|
-
if (process.env.BEAST_PYTHON) cands.push({ exe: String(process.env.BEAST_PYTHON), args: [] });
|
|
13
|
-
if (process.env.APPDATA) cands.push({ exe: path.join(process.env.APPDATA, 'beast', 'py', 'python.exe'), args: [] });
|
|
14
|
-
for (const v of ['314', '313', '312', '311', '310']) cands.push({ exe: 'C:\\Python' + v + '\\python.exe', args: [] });
|
|
15
|
-
cands.push({ exe: 'python', args: [] }, { exe: 'py', args: ['-3'] });
|
|
16
|
-
for (const c of cands) {
|
|
17
|
-
if (c.exe === 'python' || c.exe === 'py') return c;
|
|
18
|
-
try { if (fs.existsSync(c.exe)) return c; } catch (e) {}
|
|
19
|
-
}
|
|
20
|
-
return { exe: 'python', args: [] };
|
|
21
|
-
}
|
|
22
|
-
function resolveBridge() {
|
|
23
|
-
const cands = [];
|
|
24
|
-
if (process.env.BEAST_BRIDGE) cands.push(String(process.env.BEAST_BRIDGE));
|
|
25
|
-
if (process.env.BEAST_FINANCE_DIR) cands.push(path.join(String(process.env.BEAST_FINANCE_DIR), 'mt5_bridge.py'));
|
|
26
|
-
if (process.env.APPDATA) cands.push(path.join(process.env.APPDATA, 'beast', 'finance', 'mt5_bridge.py'));
|
|
27
|
-
for (const p of cands) { try { if (p && fs.existsSync(p)) return p; } catch (e) {} }
|
|
28
|
-
return cands[0] || '';
|
|
29
|
-
}
|
|
30
|
-
const PYSPEC = resolvePython();
|
|
31
|
-
const PY = PYSPEC.exe;
|
|
32
|
-
const PY_ARGS = PYSPEC.args;
|
|
33
|
-
const BRIDGE = resolveBridge();
|
|
34
|
-
|
|
35
|
-
const TIMEOUT = 35000;
|
|
36
|
-
|
|
37
|
-
function call(requests) {
|
|
38
|
-
return new Promise((resolve) => {
|
|
39
|
-
let py;
|
|
40
|
-
try { py = spawn(PY, [...PY_ARGS, BRIDGE], { windowsHide: true, stdio: ['pipe', 'pipe', 'pipe'] }); }
|
|
41
|
-
catch (e) { return resolve({ ok: false, error: 'python baslatilamadi: ' + e.message }); }
|
|
42
|
-
const results = {};
|
|
43
|
-
let buf = '';
|
|
44
|
-
let errTail = '';
|
|
45
|
-
let settled = false;
|
|
46
|
-
const finish = (obj) => { if (!settled) { settled = true; clearTimeout(timer); try { py.kill(); } catch (e) {} resolve(obj); } };
|
|
47
|
-
const timer = setTimeout(() => finish({ ok: false, error: 'zaman asimi: MT5 terminali acik ve yanit veriyor mu?' }), TIMEOUT);
|
|
48
|
-
py.stdout.on('data', (d) => {
|
|
49
|
-
buf += d.toString('utf8');
|
|
50
|
-
let i;
|
|
51
|
-
while ((i = buf.indexOf('\n')) >= 0) {
|
|
52
|
-
const line = buf.slice(0, i).trim(); buf = buf.slice(i + 1);
|
|
53
|
-
if (!line) continue;
|
|
54
|
-
let o = null;
|
|
55
|
-
try { o = JSON.parse(line); } catch (e) { continue; }
|
|
56
|
-
if (o && o.event) continue;
|
|
57
|
-
if (o && typeof o.id === 'number' && Object.prototype.hasOwnProperty.call(o, 'ok')) {
|
|
58
|
-
results[o.id] = o;
|
|
59
|
-
if (Object.keys(results).length >= requests.length) {
|
|
60
|
-
const arr = requests.map((_, k) => results[k + 1]);
|
|
61
|
-
finish(arr.length === 1 ? arr[0] : { ok: true, results: arr });
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
py.stderr.on('data', (d) => { errTail = (errTail + d.toString('utf8')).slice(-800); });
|
|
67
|
-
py.on('error', (e) => finish({ ok: false, error: 'python baslatilamadi: ' + e.message }));
|
|
68
|
-
py.on('close', (code) => { if (Object.keys(results).length < requests.length) finish({ ok: false, error: 'bridge erken cikti code=' + code + ' ' + errTail }); });
|
|
69
|
-
requests.forEach((r, k) => py.stdin.write(JSON.stringify({ id: k + 1, method: r.method, params: r.params || {} }) + '\n'));
|
|
70
|
-
py.stdin.end();
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
(async function main() {
|
|
75
|
-
let args = {};
|
|
76
|
-
try { args = JSON.parse(fs.readFileSync(0, 'utf8') || '{}'); } catch (e) {}
|
|
77
|
-
let days = Number(args.days || 1);
|
|
78
|
-
if (!(days > 0)) days = 1;
|
|
79
|
-
days = Math.min(days, 90);
|
|
80
|
-
const r = await call([{ method: 'deals', params: { days: days } }]);
|
|
81
|
-
if (r.ok && r.data) return console.log(JSON.stringify({ ok: true, count: r.data.count, deals: r.data.deals }));
|
|
82
|
-
console.log(JSON.stringify({ ok: false, error: r.error || 'gecmis alinamadi' }));
|
|
83
|
-
})();
|
|
84
|
-
|
|
85
|
-
/* PATCH 2026-09-10b: electron app-mode cocuk prosesi kapanmiyordu (90sn timeout).
|
|
86
|
-
stdout'un boruya bosalmasi icin kisa bekleme, sonra zorla cik. */
|
|
87
|
-
setTimeout(() => process.exit(0), 1500);
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "mt5_gecmis",
|
|
3
|
-
"description": "Kapanmış işlem geçmişi: son N günde kapatılan pozisyonlar/deals, kar-zarar, komisyon, swap. days verilmezse 1 gün (en fazla 90). Trader ajanları performans ve günlük P&L kontrolünde kullanır.",
|
|
4
|
-
"parameters": {
|
|
5
|
-
"type": "object",
|
|
6
|
-
"properties": {
|
|
7
|
-
"days": { "type": "number", "description": "Kac gun geriye bakilsin (1-90, varsayilan 1)" }
|
|
8
|
-
},
|
|
9
|
-
"required": []
|
|
10
|
-
},
|
|
11
|
-
"updatedAt": "2026-09-09T18:45:00.000Z"
|
|
12
|
-
}
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
// MT5 POZISYON KAPAT — stdin: JSON args · stdout: JSON sonuç
|
|
3
|
-
const { spawn } = require('child_process');
|
|
4
|
-
const fs = require('fs');
|
|
5
|
-
const path = require('path');
|
|
6
|
-
|
|
7
|
-
/* TAŞINABİLİR YOL ÇÖZÜMÜ: Beast gömülü python → sistem python'ları → PATH.
|
|
8
|
-
Köprü dosyası %APPDATA%\beast\finance\mt5_bridge.py'den (veya BEAST_FINANCE_DIR)
|
|
9
|
-
okunur; ortam değişkenleriyle geçersiz kılınabilir. */
|
|
10
|
-
function resolvePython() {
|
|
11
|
-
const cands = [];
|
|
12
|
-
if (process.env.BEAST_PYTHON) cands.push({ exe: String(process.env.BEAST_PYTHON), args: [] });
|
|
13
|
-
if (process.env.APPDATA) cands.push({ exe: path.join(process.env.APPDATA, 'beast', 'py', 'python.exe'), args: [] });
|
|
14
|
-
for (const v of ['314', '313', '312', '311', '310']) cands.push({ exe: 'C:\\Python' + v + '\\python.exe', args: [] });
|
|
15
|
-
cands.push({ exe: 'python', args: [] }, { exe: 'py', args: ['-3'] });
|
|
16
|
-
for (const c of cands) {
|
|
17
|
-
if (c.exe === 'python' || c.exe === 'py') return c;
|
|
18
|
-
try { if (fs.existsSync(c.exe)) return c; } catch (e) {}
|
|
19
|
-
}
|
|
20
|
-
return { exe: 'python', args: [] };
|
|
21
|
-
}
|
|
22
|
-
function resolveBridge() {
|
|
23
|
-
const cands = [];
|
|
24
|
-
if (process.env.BEAST_BRIDGE) cands.push(String(process.env.BEAST_BRIDGE));
|
|
25
|
-
if (process.env.BEAST_FINANCE_DIR) cands.push(path.join(String(process.env.BEAST_FINANCE_DIR), 'mt5_bridge.py'));
|
|
26
|
-
if (process.env.APPDATA) cands.push(path.join(process.env.APPDATA, 'beast', 'finance', 'mt5_bridge.py'));
|
|
27
|
-
for (const p of cands) { try { if (p && fs.existsSync(p)) return p; } catch (e) {} }
|
|
28
|
-
return cands[0] || '';
|
|
29
|
-
}
|
|
30
|
-
const PYSPEC = resolvePython();
|
|
31
|
-
const PY = PYSPEC.exe;
|
|
32
|
-
const PY_ARGS = PYSPEC.args;
|
|
33
|
-
const BRIDGE = resolveBridge();
|
|
34
|
-
|
|
35
|
-
const TIMEOUT = 35000;
|
|
36
|
-
|
|
37
|
-
function call(requests) {
|
|
38
|
-
return new Promise((resolve) => {
|
|
39
|
-
let py;
|
|
40
|
-
try { py = spawn(PY, [...PY_ARGS, BRIDGE], { windowsHide: true, stdio: ['pipe', 'pipe', 'pipe'] }); }
|
|
41
|
-
catch (e) { return resolve({ ok: false, error: 'python baslatilamadi: ' + e.message }); }
|
|
42
|
-
const results = {};
|
|
43
|
-
let buf = '';
|
|
44
|
-
let errTail = '';
|
|
45
|
-
let settled = false;
|
|
46
|
-
const finish = (obj) => { if (!settled) { settled = true; clearTimeout(timer); try { py.kill(); } catch (e) {} resolve(obj); } };
|
|
47
|
-
const timer = setTimeout(() => finish({ ok: false, error: 'zaman asimi: MT5 terminali acik ve yanit veriyor mu?' }), TIMEOUT);
|
|
48
|
-
py.stdout.on('data', (d) => {
|
|
49
|
-
buf += d.toString('utf8');
|
|
50
|
-
let i;
|
|
51
|
-
while ((i = buf.indexOf('\n')) >= 0) {
|
|
52
|
-
const line = buf.slice(0, i).trim(); buf = buf.slice(i + 1);
|
|
53
|
-
if (!line) continue;
|
|
54
|
-
let o = null;
|
|
55
|
-
try { o = JSON.parse(line); } catch (e) { continue; }
|
|
56
|
-
if (o && o.event) continue;
|
|
57
|
-
if (o && typeof o.id === 'number' && Object.prototype.hasOwnProperty.call(o, 'ok')) {
|
|
58
|
-
results[o.id] = o;
|
|
59
|
-
if (Object.keys(results).length >= requests.length) {
|
|
60
|
-
const arr = requests.map((_, k) => results[k + 1]);
|
|
61
|
-
finish(arr.length === 1 ? arr[0] : { ok: true, results: arr });
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
py.stderr.on('data', (d) => { errTail = (errTail + d.toString('utf8')).slice(-800); });
|
|
67
|
-
py.on('error', (e) => finish({ ok: false, error: 'python baslatilamadi: ' + e.message }));
|
|
68
|
-
py.on('close', (code) => { if (Object.keys(results).length < requests.length) finish({ ok: false, error: 'bridge erken cikti code=' + code + ' ' + errTail }); });
|
|
69
|
-
requests.forEach((r, k) => py.stdin.write(JSON.stringify({ id: k + 1, method: r.method, params: r.params || {} }) + '\n'));
|
|
70
|
-
py.stdin.end();
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
(async function main() {
|
|
75
|
-
let args = {};
|
|
76
|
-
try { args = JSON.parse(fs.readFileSync(0, 'utf8') || '{}'); } catch (e) {}
|
|
77
|
-
const ticket = Number(args.ticket || 0);
|
|
78
|
-
if (!ticket) return console.log(JSON.stringify({ ok: false, error: 'ticket zorunlu' }));
|
|
79
|
-
/* KISMİ KAPATMA (kısmi TP / kısmi stop): percent verilirse pozisyon
|
|
80
|
-
hacminden hesaplanır; hacim verilmezse tamamı kapanır. Kalan kısım
|
|
81
|
-
broker minimumunun (0.01) altındaysa tamamı kapatılır. */
|
|
82
|
-
const percent = Math.max(0, Math.min(100, Number(args.percent) || 0));
|
|
83
|
-
let volume = Number(args.volume || 0);
|
|
84
|
-
let pvol = 0;
|
|
85
|
-
if (percent > 0 && !(volume > 0)) {
|
|
86
|
-
const pr = await call([{ method: 'positions', params: {} }]);
|
|
87
|
-
const list = (pr.ok && pr.data && pr.data.positions) || [];
|
|
88
|
-
const pos = list.find((p) => Number(p.ticket) === ticket);
|
|
89
|
-
if (!pos) return console.log(JSON.stringify({ ok: false, error: 'pozisyon bulunamadi: ' + ticket }));
|
|
90
|
-
pvol = Number(pos.volume) || 0;
|
|
91
|
-
volume = Math.floor(((pvol * percent) / 100) * 100) / 100;
|
|
92
|
-
if (!(volume > 0)) return console.log(JSON.stringify({ ok: false, error: 'percent sonucu hacim sifir cikti (pozisyon ' + pvol + ' lot)' }));
|
|
93
|
-
if (pvol - volume > 0 && pvol - volume < 0.01 - 1e-9) volume = pvol; /* kalan minimumun altinda → tamami */
|
|
94
|
-
}
|
|
95
|
-
const params = { ticket: ticket };
|
|
96
|
-
if (volume > 0) params.volume = volume;
|
|
97
|
-
const r = await call([{ method: 'close', params: params }]);
|
|
98
|
-
if (r.ok && r.data && r.data.result) {
|
|
99
|
-
const res = r.data.result;
|
|
100
|
-
console.log(JSON.stringify({ ok: true, retcode: res.retcode, comment: res.comment, kismi: pvol > 0 && volume < pvol, kapatilan: volume || 'tamami', detay: r.data }));
|
|
101
|
-
} else {
|
|
102
|
-
console.log(JSON.stringify({ ok: false, error: r.error || 'kapatma reddedildi' }));
|
|
103
|
-
}
|
|
104
|
-
})();
|
|
105
|
-
|
|
106
|
-
/* PATCH 2026-09-10b: electron app-mode cocuk prosesi kapanmiyordu (90sn timeout).
|
|
107
|
-
stdout'un boruya bosalmasi icin kisa bekleme, sonra zorla cik. */
|
|
108
|
-
setTimeout(() => process.exit(0), 1500);
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "mt5_kapat",
|
|
3
|
-
"description": "Açık pozisyonu kapatır — TAM ya da KISMİ: ticket zorunlu; percent (pozisyonun % kaçı, ör. 50) ya da volume (lot) verilebilir. Kısmi kapatma = kısmi TP (kâr al) / kısmi stop (zarar kes) — kararı ajan verir, otomatik değildir. Kalan kısım SL/TP ile devam eder; kalan lot 0.01 altında kalırsa tamamı kapanır. Başarıda kapanış sonucu döner.",
|
|
4
|
-
"parameters": {
|
|
5
|
-
"type": "object",
|
|
6
|
-
"properties": {
|
|
7
|
-
"ticket": { "type": "number", "description": "Kapatilacak pozisyonun ticket numarasi" },
|
|
8
|
-
"percent": { "type": "number", "description": "Kapatilacak yuzde (ör. 50) — kısmi TP/kısmi stop icin" },
|
|
9
|
-
"volume": { "type": "number", "description": "Kapatilacak lot (percent yerine; ikisi de yoksa tamami kapanir)" }
|
|
10
|
-
},
|
|
11
|
-
"required": ["ticket"]
|
|
12
|
-
},
|
|
13
|
-
"defaultsVersion": 2,
|
|
14
|
-
"updatedAt": "2026-09-15T15:00:00.000Z"
|
|
15
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
"""mt5_m15_m5 - SALT-OKUNUR yardimci. GOLD M15 + M5 son 12 bar + canli fiyat.
|
|
2
|
-
Arguman ALMAZ. Kopruye (mt5_bridge.py) DOKUNMAZ, ayri surecte calisir.
|
|
3
|
-
hicbir order_send / order_check / positions_close cagrisi YOKTUR.
|
|
4
|
-
Cikti: stdout'a TEK satir JSON, 2000 baytin altinda.
|
|
5
|
-
"""
|
|
6
|
-
import sys, json, datetime
|
|
7
|
-
|
|
8
|
-
SYM = "GOLD"
|
|
9
|
-
TERM = r"C:\Program Files\FxPro - MetaTrader 5\terminal64.exe"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def emit(o, code=0):
|
|
13
|
-
sys.stdout.write(json.dumps(o, separators=(",", ":")))
|
|
14
|
-
sys.stdout.flush()
|
|
15
|
-
sys.exit(code)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
try:
|
|
19
|
-
import MetaTrader5 as mt5
|
|
20
|
-
except Exception as e:
|
|
21
|
-
emit({"ok": False, "error": "modul yuklenemedi: " + type(e).__name__}, 1)
|
|
22
|
-
|
|
23
|
-
if not mt5.initialize(path=TERM):
|
|
24
|
-
if not mt5.initialize():
|
|
25
|
-
emit({"ok": False, "error": "mt5 initialize basarisiz"}, 1)
|
|
26
|
-
|
|
27
|
-
try:
|
|
28
|
-
si = mt5.symbol_info(SYM)
|
|
29
|
-
if si is None:
|
|
30
|
-
emit({"ok": False, "error": "sembol yok: " + SYM}, 1)
|
|
31
|
-
if not si.visible:
|
|
32
|
-
mt5.symbol_select(SYM, True)
|
|
33
|
-
|
|
34
|
-
def bars(tf_const, n=12):
|
|
35
|
-
r = mt5.copy_rates_from_pos(SYM, tf_const, 0, n)
|
|
36
|
-
if r is None or len(r) == 0:
|
|
37
|
-
return []
|
|
38
|
-
return [[int(x["time"]), round(float(x["open"]), 2), round(float(x["high"]), 2),
|
|
39
|
-
round(float(x["low"]), 2), round(float(x["close"]), 2)] for x in r]
|
|
40
|
-
|
|
41
|
-
m15 = bars(mt5.TIMEFRAME_M15, 12)
|
|
42
|
-
m5 = bars(mt5.TIMEFRAME_M5, 12)
|
|
43
|
-
if not m15 and not m5:
|
|
44
|
-
emit({"ok": False, "error": "bar alinamadi: " + SYM}, 1)
|
|
45
|
-
|
|
46
|
-
tk = mt5.symbol_info_tick(SYM)
|
|
47
|
-
if tk is None:
|
|
48
|
-
st, bid, ask, sp = "--:--", 0, 0, 0
|
|
49
|
-
else:
|
|
50
|
-
bid, ask = round(float(tk.bid), 2), round(float(tk.ask), 2)
|
|
51
|
-
sp = round(ask - bid, 2)
|
|
52
|
-
st = datetime.datetime.fromtimestamp(int(tk.time), datetime.timezone.utc).strftime("%H:%M")
|
|
53
|
-
|
|
54
|
-
emit({"ok": True, "server_time": st, "bid": bid, "ask": ask, "spread": sp,
|
|
55
|
-
"m15": m15, "m5": m5}, 0)
|
|
56
|
-
finally:
|
|
57
|
-
try:
|
|
58
|
-
mt5.shutdown()
|
|
59
|
-
except Exception:
|
|
60
|
-
pass
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
/* mt5_m15_m5 - PARAMETRE ALMAZ (argumansiz yedek yol).
|
|
3
|
-
C:\Python314\python.exe ile yanindaki m15m5.py dosyasini calistirir,
|
|
4
|
-
stdout'a TEK satir JSON basar. SALT-OKUNUR: hicbir islem/pending/close cagrisi yok.
|
|
5
|
-
Cikti alanlari: ok, server_time, bid, ask, spread, m15[12], m5[12] -> [epoch,o,h,l,c]
|
|
6
|
-
stdout sert sinir: 2000 bayt. */
|
|
7
|
-
const fs = require('fs');
|
|
8
|
-
const path = require('path');
|
|
9
|
-
const { spawnSync } = require('child_process');
|
|
10
|
-
function resolvePython() {
|
|
11
|
-
const cands = [];
|
|
12
|
-
if (process.env.BEAST_PYTHON) cands.push({ exe: String(process.env.BEAST_PYTHON), args: [] });
|
|
13
|
-
if (process.env.APPDATA) cands.push({ exe: require('path').join(process.env.APPDATA, 'beast', 'py', 'python.exe'), args: [] });
|
|
14
|
-
for (const v of ['314', '313', '312', '311', '310']) cands.push({ exe: 'C:\\Python' + v + '\\python.exe', args: [] });
|
|
15
|
-
cands.push({ exe: 'python', args: [] }, { exe: 'py', args: ['-3'] });
|
|
16
|
-
for (const c of cands) {
|
|
17
|
-
if (c.exe === 'python' || c.exe === 'py') return c;
|
|
18
|
-
try { if (fs.existsSync(c.exe)) return c; } catch (e) {}
|
|
19
|
-
}
|
|
20
|
-
return { exe: 'python', args: [] };
|
|
21
|
-
}
|
|
22
|
-
const PYSPEC = resolvePython();
|
|
23
|
-
const PY = PYSPEC.exe;
|
|
24
|
-
const PY_ARGS = PYSPEC.args;
|
|
25
|
-
|
|
26
|
-
const SCRIPT = path.join(__dirname, 'm15m5.py');
|
|
27
|
-
const LIMIT = 2000;
|
|
28
|
-
|
|
29
|
-
function emit(o, code) {
|
|
30
|
-
process.stdout.write(JSON.stringify(o));
|
|
31
|
-
process.exit(code || 0);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
(function main() {
|
|
35
|
-
// parametre almaz: stdin'i beklemeden sessizce yut, araclar arasi kalmasin
|
|
36
|
-
try {
|
|
37
|
-
process.stdin.on('error', () => {});
|
|
38
|
-
process.stdin.on('data', () => {});
|
|
39
|
-
process.stdin.resume();
|
|
40
|
-
} catch { }
|
|
41
|
-
|
|
42
|
-
if (!fs.existsSync(SCRIPT)) return emit({ ok: false, error: 'm15m5.py yok: ' + SCRIPT }, 1);
|
|
43
|
-
|
|
44
|
-
let r;
|
|
45
|
-
try {
|
|
46
|
-
r = spawnSync(PY, [...PY_ARGS, SCRIPT], { encoding: 'utf8', timeout: 60000, windowsHide: true });
|
|
47
|
-
} catch (e) {
|
|
48
|
-
return emit({ ok: false, error: 'python baslatilamadi: ' + String((e && e.message) || e).slice(0, 140) }, 1);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const out = String((r && r.stdout) || '').trim();
|
|
52
|
-
if (out) {
|
|
53
|
-
let parsed = null;
|
|
54
|
-
try { parsed = JSON.parse(out); } catch { }
|
|
55
|
-
if (parsed && typeof parsed === 'object') {
|
|
56
|
-
const packed = JSON.stringify(parsed);
|
|
57
|
-
const bytes = Buffer.byteLength(packed, 'utf8');
|
|
58
|
-
if (bytes > LIMIT) return emit({ ok: false, error: 'cikti siniri asildi', bytes: bytes, limit: LIMIT }, 1);
|
|
59
|
-
return emit(parsed, parsed.ok ? 0 : 1);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
emit({
|
|
64
|
-
ok: false,
|
|
65
|
-
error: 'python cikti yok/kirik',
|
|
66
|
-
exit_code: r && r.status,
|
|
67
|
-
stderr: String((r && r.stderr) || '').trim().slice(0, 300),
|
|
68
|
-
}, 1);
|
|
69
|
-
})();
|
|
70
|
-
|
|
71
|
-
/* PATCH 2026-09-10b: electron app-mode cocuk prosesi kapanmiyordu (90sn timeout).
|
|
72
|
-
stdout'un boruya bosalmasi icin kisa bekleme, sonra zorla cik. */
|
|
73
|
-
setTimeout(() => process.exit(0), 1500);
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "mt5_m15_m5",
|
|
3
|
-
"description": "PARAMETRE ALMAZ (argumansiz cagrilir). SALT-OKUNUR, islem acmaz. C:\\Python314\\python.exe ile MetaTrader5 modulunu DOGRUDAN kullanip GOLD icin tek satir JSON dondurur: server_time (HH:MM), bid, ask, spread, m15 (son 12 M15 bari), m5 (son 12 M5 bari) - barlar [epoch,o,h,l,c] biciminde eskiden yeniye. Amac: parametre gecirmeyen runner icin parametresiz yedek yol.",
|
|
4
|
-
"parameters": {
|
|
5
|
-
"type": "object",
|
|
6
|
-
"properties": {},
|
|
7
|
-
"required": []
|
|
8
|
-
},
|
|
9
|
-
"updatedAt": "2026-09-10T10:05:00.000Z"
|
|
10
|
-
}
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
// MT5 POZISYON BAZLI GECMIS — açılış+kapanış tek satırda birleşik.
|
|
3
|
-
// stdin: JSON args · stdout: JSON sonuç (SADECE JSON yaz!)
|
|
4
|
-
const { spawn } = require('child_process');
|
|
5
|
-
const fs = require('fs');
|
|
6
|
-
const path = require('path');
|
|
7
|
-
|
|
8
|
-
/* TAŞINABİLİR YOL ÇÖZÜMÜ: Beast gömülü python → sistem python'ları → PATH.
|
|
9
|
-
Köprü dosyası %APPDATA%\beast\finance\mt5_bridge.py'den (veya BEAST_FINANCE_DIR)
|
|
10
|
-
okunur; ortam değişkenleriyle geçersiz kılınabilir. */
|
|
11
|
-
function resolvePython() {
|
|
12
|
-
const cands = [];
|
|
13
|
-
if (process.env.BEAST_PYTHON) cands.push({ exe: String(process.env.BEAST_PYTHON), args: [] });
|
|
14
|
-
if (process.env.APPDATA) cands.push({ exe: path.join(process.env.APPDATA, 'beast', 'py', 'python.exe'), args: [] });
|
|
15
|
-
for (const v of ['314', '313', '312', '311', '310']) cands.push({ exe: 'C:\\Python' + v + '\\python.exe', args: [] });
|
|
16
|
-
cands.push({ exe: 'python', args: [] }, { exe: 'py', args: ['-3'] });
|
|
17
|
-
for (const c of cands) {
|
|
18
|
-
if (c.exe === 'python' || c.exe === 'py') return c;
|
|
19
|
-
try { if (fs.existsSync(c.exe)) return c; } catch (e) {}
|
|
20
|
-
}
|
|
21
|
-
return { exe: 'python', args: [] };
|
|
22
|
-
}
|
|
23
|
-
function resolveBridge() {
|
|
24
|
-
const cands = [];
|
|
25
|
-
if (process.env.BEAST_BRIDGE) cands.push(String(process.env.BEAST_BRIDGE));
|
|
26
|
-
if (process.env.BEAST_FINANCE_DIR) cands.push(path.join(String(process.env.BEAST_FINANCE_DIR), 'mt5_bridge.py'));
|
|
27
|
-
if (process.env.APPDATA) cands.push(path.join(process.env.APPDATA, 'beast', 'finance', 'mt5_bridge.py'));
|
|
28
|
-
for (const p of cands) { try { if (p && fs.existsSync(p)) return p; } catch (e) {} }
|
|
29
|
-
return cands[0] || '';
|
|
30
|
-
}
|
|
31
|
-
const PYSPEC = resolvePython();
|
|
32
|
-
const PY = PYSPEC.exe;
|
|
33
|
-
const PY_ARGS = PYSPEC.args;
|
|
34
|
-
const BRIDGE = resolveBridge();
|
|
35
|
-
|
|
36
|
-
const TIMEOUT = 35000;
|
|
37
|
-
|
|
38
|
-
function call(requests) {
|
|
39
|
-
return new Promise((resolve) => {
|
|
40
|
-
let py;
|
|
41
|
-
try { py = spawn(PY, [...PY_ARGS, BRIDGE], { windowsHide: true, stdio: ['pipe', 'pipe', 'pipe'] }); }
|
|
42
|
-
catch (e) { return resolve({ ok: false, error: 'python baslatilamadi: ' + e.message }); }
|
|
43
|
-
const results = {};
|
|
44
|
-
let buf = '';
|
|
45
|
-
let errTail = '';
|
|
46
|
-
let settled = false;
|
|
47
|
-
const finish = (obj) => { if (!settled) { settled = true; clearTimeout(timer); try { py.kill(); } catch (e) {} resolve(obj); } };
|
|
48
|
-
const timer = setTimeout(() => finish({ ok: false, error: 'zaman asimi: MT5 terminali acik ve yanit veriyor mu?' }), TIMEOUT);
|
|
49
|
-
py.stdout.on('data', (d) => {
|
|
50
|
-
buf += d.toString('utf8');
|
|
51
|
-
let i;
|
|
52
|
-
while ((i = buf.indexOf('\n')) >= 0) {
|
|
53
|
-
const line = buf.slice(0, i).trim(); buf = buf.slice(i + 1);
|
|
54
|
-
if (!line) continue;
|
|
55
|
-
let o = null;
|
|
56
|
-
try { o = JSON.parse(line); } catch (e) { continue; }
|
|
57
|
-
if (o && o.event) continue;
|
|
58
|
-
if (o && typeof o.id === 'number' && Object.prototype.hasOwnProperty.call(o, 'ok')) {
|
|
59
|
-
results[o.id] = o;
|
|
60
|
-
if (Object.keys(results).length >= requests.length) {
|
|
61
|
-
const arr = requests.map((_, k) => results[k + 1]);
|
|
62
|
-
finish(arr.length === 1 ? arr[0] : { ok: true, results: arr });
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
py.stderr.on('data', (d) => { errTail = (errTail + d.toString('utf8')).slice(-800); });
|
|
68
|
-
py.on('error', (e) => finish({ ok: false, error: 'python baslatilamadi: ' + e.message }));
|
|
69
|
-
py.on('close', (code) => { if (Object.keys(results).length < requests.length) finish({ ok: false, error: 'bridge erken cikti code=' + code + ' ' + errTail }); });
|
|
70
|
-
requests.forEach((r, k) => py.stdin.write(JSON.stringify({ id: k + 1, method: r.method, params: r.params || {} }) + '\n'));
|
|
71
|
-
py.stdin.end();
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const r2 = (n) => Math.round((Number(n) || 0) * 100) / 100;
|
|
76
|
-
const fmt = (t) => {
|
|
77
|
-
if (!t) return '';
|
|
78
|
-
const d = new Date(Number(t) * 1000);
|
|
79
|
-
const p = (x) => String(x).padStart(2, '0');
|
|
80
|
-
return d.getFullYear() + '-' + p(d.getMonth() + 1) + '-' + p(d.getDate()) + ' ' + p(d.getHours()) + ':' + p(d.getMinutes());
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
(async function main() {
|
|
84
|
-
let args = {};
|
|
85
|
-
try { args = JSON.parse(fs.readFileSync(0, 'utf8') || '{}'); } catch (e) {}
|
|
86
|
-
let days = Number(args.days || 1);
|
|
87
|
-
if (!(days > 0)) days = 1;
|
|
88
|
-
days = Math.min(days, 90);
|
|
89
|
-
const r = await call([{ method: 'deals', params: { days: days } }]);
|
|
90
|
-
if (!r.ok || !r.data) return console.log(JSON.stringify({ ok: false, error: r.error || 'gecmis alinamadi' }));
|
|
91
|
-
|
|
92
|
-
const deals = r.data.deals || [];
|
|
93
|
-
if (!deals.length) return console.log(JSON.stringify({ ok: true, count: 0, positions: [], summary: { net: 0, wins: 0, losses: 0 } }));
|
|
94
|
-
|
|
95
|
-
// Ayni position_id -> tek pozisyon. INOUT (entry=2) deal'ler kendi basina pozisyon.
|
|
96
|
-
const byPos = new Map();
|
|
97
|
-
for (const dl of deals) {
|
|
98
|
-
const pid = (dl.position_id != null && dl.position_id !== 0) ? dl.position_id : dl.ticket;
|
|
99
|
-
if (!byPos.has(pid)) byPos.set(pid, []);
|
|
100
|
-
byPos.get(pid).push(dl);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const positions = [];
|
|
104
|
-
for (const [pid, arr] of byPos) {
|
|
105
|
-
arr.sort((a, b) => (a.time || 0) - (b.time || 0));
|
|
106
|
-
const first = arr[0];
|
|
107
|
-
const entryDeal = arr.find((x) => x.entry === 0) || first;
|
|
108
|
-
const exitDeal = arr.find((x) => x.entry === 1) || arr[arr.length - 1];
|
|
109
|
-
let profit = 0, commission = 0, swap = 0;
|
|
110
|
-
for (const x of arr) { profit += Number(x.profit) || 0; commission += Number(x.commission) || 0; swap += Number(x.swap) || 0; }
|
|
111
|
-
positions.push({
|
|
112
|
-
position_id: pid,
|
|
113
|
-
symbol: first.symbol,
|
|
114
|
-
side: Number(first.type) === 0 ? 'buy' : 'sell',
|
|
115
|
-
volume: r2(first.volume),
|
|
116
|
-
open_price: entryDeal.price,
|
|
117
|
-
open_time: entryDeal.time,
|
|
118
|
-
open_time_str: fmt(entryDeal.time),
|
|
119
|
-
close_price: exitDeal.price,
|
|
120
|
-
close_time: exitDeal.time,
|
|
121
|
-
close_time_str: fmt(exitDeal.time),
|
|
122
|
-
profit: r2(profit),
|
|
123
|
-
commission: r2(commission),
|
|
124
|
-
swap: r2(swap),
|
|
125
|
-
net: r2(profit + commission + swap),
|
|
126
|
-
deal_count: arr.length
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
positions.sort((a, b) => (b.close_time || 0) - (a.close_time || 0));
|
|
130
|
-
|
|
131
|
-
let net = 0, wins = 0, losses = 0;
|
|
132
|
-
for (const p of positions) { net += p.net; if (p.net > 0) wins++; else if (p.net < 0) losses++; }
|
|
133
|
-
|
|
134
|
-
console.log(JSON.stringify({
|
|
135
|
-
ok: true,
|
|
136
|
-
count: positions.length,
|
|
137
|
-
positions: positions,
|
|
138
|
-
summary: { net: r2(net), wins: wins, losses: losses }
|
|
139
|
-
}));
|
|
140
|
-
})();
|
|
141
|
-
|
|
142
|
-
/* PATCH 2026-09-10b: electron app-mode cocuk prosesi kapanmiyordu (90sn timeout).
|
|
143
|
-
stdout'un boruya bosalmasi icin kisa bekleme, sonra zorla cik. */
|
|
144
|
-
setTimeout(() => process.exit(0), 1500);
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "mt5_pozisyon_gecmis",
|
|
3
|
-
"description": "Kapanan pozisyon geçmişi — açılış ve kapanış TEK SATIRDA birleşik gösterilir (deal'ler ayrı ayrı değil). Sembol, yön, lot, açılış/kapanış fiyatı ve zamanı, net kâr/zarar (profit+komisyon+swap). days verilmezse bugün (en fazla 90).",
|
|
4
|
-
"parameters": {
|
|
5
|
-
"type": "object",
|
|
6
|
-
"properties": {
|
|
7
|
-
"days": { "type": "number", "description": "Kac gun geriye bakilsin (1-90, varsayilan 1 = bugun)" }
|
|
8
|
-
},
|
|
9
|
-
"required": []
|
|
10
|
-
},
|
|
11
|
-
"updatedAt": "2026-09-09T22:10:00.000Z"
|
|
12
|
-
}
|