beast-agent 2.74.0 → 2.76.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/financetools.js +2 -1
- package/src/main.js +148 -17
- package/src/renderer/index.html +6 -2
- package/src/renderer/renderer.js +13 -7
package/package.json
CHANGED
|
@@ -802,7 +802,8 @@ const handlers = {
|
|
|
802
802
|
}
|
|
803
803
|
const pos = await bcall('positions', {}, 8000);
|
|
804
804
|
const list = (pos && pos.positions) || [];
|
|
805
|
-
|
|
805
|
+
/* EFEKTİF TAVAN: talimattaki "en fazla N işlem/pozisyon" ayarı ezer */
|
|
806
|
+
const maxPos = Number(cfg.maxPositionsNote) > 0 ? Number(cfg.maxPositionsNote) : Number(cfg.maxPositions) || 3;
|
|
806
807
|
if (list.length >= maxPos) {
|
|
807
808
|
return { ok: false, error: `max eşzamanlı pozisyon dolu (${list.length}/${maxPos}) — önce bir pozisyon kapat` };
|
|
808
809
|
}
|
package/src/main.js
CHANGED
|
@@ -9906,7 +9906,8 @@ const financeState = {
|
|
|
9906
9906
|
watchTickAt: 0,
|
|
9907
9907
|
/* POZİSYON YÖNETİCİSİ (JEV): açık pozisyon varken 5 sn'lik watchdog turundan
|
|
9908
9908
|
tetiklenen ayrı Jev ajanı — kapat/kısmi/SL kararlarını kendi talimatıyla verir */
|
|
9909
|
-
posManager: { busy: false, rounds: 0, lastAt: 0, lastErr: '', lastPosCount: 0, tsPartials: new Set() },
|
|
9909
|
+
posManager: { busy: false, rounds: 0, lastAt: 0, lastErr: '', lastPosCount: 0, timer: null, tsPartials: new Set() },
|
|
9910
|
+
posSnapshot: null, /* son watchdog turunun pozisyon/hesap anlık görüntüsü (yönetici yeniden kullanır) */
|
|
9910
9911
|
hoursTimer: null, /* trade saatleri otomatik duraklatma denetimi (10 sn) */
|
|
9911
9912
|
hoursPaused: null, /* pencere kapanınca durdurulan ajanların planı — açılınca geri gelir */
|
|
9912
9913
|
alerts: [], /* fiyat alarmları (kalıcı: finance/alerts.json) */
|
|
@@ -10018,12 +10019,36 @@ function finCfg() {
|
|
|
10018
10019
|
try { saveSettings(); } catch {}
|
|
10019
10020
|
}
|
|
10020
10021
|
if (!Number.isFinite(Number(f.maxPerCurrency))) f.maxPerCurrency = 3;
|
|
10022
|
+
/* TALİMATTAN ÜST SINIR: "aynı anda en fazla 10 işlem/pozisyon" → eşzamanlı
|
|
10023
|
+
tavan; "günde en fazla 10 işlem" → günlük işlem tavanı. Ayarı KALICI
|
|
10024
|
+
ezmez: not yalnız talimat metninde durdukça geçerlidir (0 = not yok). */
|
|
10025
|
+
f.maxPositionsNote = 0;
|
|
10026
|
+
f.maxTradesPerDayNote = 0;
|
|
10027
|
+
try {
|
|
10028
|
+
const txt = (String(f.strategy || '') + '\n' + String(f.posManagerNote || '')).toLowerCase();
|
|
10029
|
+
const re = /(en\s*fazla|en\s*[çc]ok|max(?:imum)?|maks(?:imum)?)\s*(\d{1,2})\s*(?:i[şs]lem|islem|trade|emir|pozisyon|poz)/g;
|
|
10030
|
+
let mm;
|
|
10031
|
+
while ((mm = re.exec(txt))) {
|
|
10032
|
+
const n = Number(mm[2]);
|
|
10033
|
+
if (!(n >= 1 && n <= 20)) continue;
|
|
10034
|
+
/* GÜNLÜK ayrımı: "günde/günlük/gün içinde ... en fazla N işlem" — cümle
|
|
10035
|
+
sınırı (nokta/virgül) aşılmaz; "günlük zarar %3, maks 4 pozisyon"
|
|
10036
|
+
ifadesindeki "günlük" günlük tavana YAZILMAZ, eşzamanlı sayılır. */
|
|
10037
|
+
const before = txt.slice(0, mm.index);
|
|
10038
|
+
const daily = /(?:g[üu]nde|g[üu]nl[üu]k|g[üu]n\s*i[çc]inde)[^.;,\n]{0,14}$/.test(before);
|
|
10039
|
+
if (daily) f.maxTradesPerDayNote = n;
|
|
10040
|
+
else if (!f.maxPositionsNote) f.maxPositionsNote = n; /* eşzamanlı tavan */
|
|
10041
|
+
}
|
|
10042
|
+
} catch {}
|
|
10021
10043
|
/* SHADOW MOD: emir gönderilmez — kararlar gerekçesiyle günlüğe yazılır */
|
|
10022
10044
|
if (typeof f.shadowMode !== 'boolean') f.shadowMode = false;
|
|
10023
10045
|
/* POZİSYON YÖNETİCİSİ: açık pozisyonları 5 sn'de bir Jev ile yöneten ayrı
|
|
10024
10046
|
ajan — varsayılan AÇIK; kendi talimatı (posManagerNote) yalnız onu bağlar. */
|
|
10025
10047
|
if (typeof f.posManagerEnabled !== 'boolean') f.posManagerEnabled = true;
|
|
10026
10048
|
if (typeof f.posManagerNote !== 'string') f.posManagerNote = '';
|
|
10049
|
+
/* Yönetici kontrol sıklığı (sn): 1-300; varsayılan 5 */
|
|
10050
|
+
if (!Number.isFinite(Number(f.posManagerSec))) f.posManagerSec = 5;
|
|
10051
|
+
f.posManagerSec = Math.max(1, Math.min(300, Math.round(Number(f.posManagerSec) || 5)));
|
|
10027
10052
|
/* GÜNLÜK RUTİN: plan/review saatleri (HH:MM; boş = kapalı) — hafta içi cron */
|
|
10028
10053
|
if (typeof f.planTime !== 'string') f.planTime = '';
|
|
10029
10054
|
if (typeof f.reviewTime !== 'string') f.reviewTime = '';
|
|
@@ -10379,12 +10404,31 @@ function finTeamDigest() {
|
|
|
10379
10404
|
/* KODLA DİSİPLİN kancası: financetools işlem öncesi bunu çağırır. */
|
|
10380
10405
|
function finDisciplineError(side, symbol, positions) {
|
|
10381
10406
|
try {
|
|
10382
|
-
|
|
10407
|
+
const cfg = finCfg();
|
|
10408
|
+
/* TALİMAT: "günde en fazla N işlem" → günlük işlem tavanını ezer */
|
|
10409
|
+
if (Number(cfg.maxTradesPerDayNote) > 0) {
|
|
10410
|
+
return finrisk.disciplineError(
|
|
10411
|
+
finJournalTail(400),
|
|
10412
|
+
Date.now(),
|
|
10413
|
+
{ ...cfg, maxTradesPerDay: Number(cfg.maxTradesPerDayNote) },
|
|
10414
|
+
side,
|
|
10415
|
+
symbol,
|
|
10416
|
+
positions
|
|
10417
|
+
);
|
|
10418
|
+
}
|
|
10419
|
+
return finrisk.disciplineError(finJournalTail(400), Date.now(), cfg, side, symbol, positions);
|
|
10383
10420
|
} catch {
|
|
10384
10421
|
return null;
|
|
10385
10422
|
}
|
|
10386
10423
|
}
|
|
10387
10424
|
|
|
10425
|
+
/* EFEKTİF POZİSYON TAVANI: talimattaki "en fazla N işlem/pozisyon" ayarı ezer */
|
|
10426
|
+
function finPosCap(f) {
|
|
10427
|
+
const note = Number(f && f.maxPositionsNote) > 0 ? Number(f.maxPositionsNote) : 0;
|
|
10428
|
+
const base = Number(f && f.maxPositions) || 3;
|
|
10429
|
+
return Math.max(1, Math.min(20, note > 0 ? note : base));
|
|
10430
|
+
}
|
|
10431
|
+
|
|
10388
10432
|
/* ---------- MAE/MFE: pozisyonun gördüğü en iyi/en kötü seviye ---------- */
|
|
10389
10433
|
function finExcLoad() {
|
|
10390
10434
|
try {
|
|
@@ -11624,10 +11668,13 @@ async function finWatchTick() {
|
|
|
11624
11668
|
try { await finRecordClose(ticket, st); } catch {}
|
|
11625
11669
|
}
|
|
11626
11670
|
}
|
|
11627
|
-
/* POZİSYON YÖNETİCİSİ (JEV):
|
|
11628
|
-
|
|
11629
|
-
if (positionsOk
|
|
11630
|
-
|
|
11671
|
+
/* POZİSYON YÖNETİCİSİ (JEV): pozisyon anlık görüntüsü saklanır (yönetici
|
|
11672
|
+
kendi zamanlayıcısında yeniden kullanır) + tur burada da tetiklenir */
|
|
11673
|
+
if (positionsOk) {
|
|
11674
|
+
financeState.posSnapshot = { at: Date.now(), positions, account };
|
|
11675
|
+
if (positions.length) {
|
|
11676
|
+
try { finPosManagerMaybe(positions, account); } catch {}
|
|
11677
|
+
}
|
|
11631
11678
|
}
|
|
11632
11679
|
try { await finCheckAlerts(); } catch {}
|
|
11633
11680
|
if (!financeState.lastStatsAt || Date.now() - financeState.lastStatsAt > 120000) {
|
|
@@ -11643,9 +11690,12 @@ async function finWatchTick() {
|
|
|
11643
11690
|
}
|
|
11644
11691
|
|
|
11645
11692
|
function finWatchStart() {
|
|
11646
|
-
if (financeState.watchTimer)
|
|
11647
|
-
|
|
11648
|
-
|
|
11693
|
+
if (!financeState.watchTimer) {
|
|
11694
|
+
financeState.watchTimer = setInterval(() => { finWatchTick().catch(() => {}); }, 5000);
|
|
11695
|
+
finWatchTick().catch(() => {});
|
|
11696
|
+
}
|
|
11697
|
+
/* Pozisyon yöneticisinin KENDİ zamanlayıcısı (ayarlı aralık; 1-300 sn) */
|
|
11698
|
+
try { finPosManagerStart(); } catch {}
|
|
11649
11699
|
}
|
|
11650
11700
|
|
|
11651
11701
|
function finWatchStop() {
|
|
@@ -11653,6 +11703,7 @@ function finWatchStop() {
|
|
|
11653
11703
|
clearInterval(financeState.watchTimer);
|
|
11654
11704
|
financeState.watchTimer = null;
|
|
11655
11705
|
}
|
|
11706
|
+
try { finPosManagerStop(); } catch {}
|
|
11656
11707
|
}
|
|
11657
11708
|
|
|
11658
11709
|
function finWatchLoad() {
|
|
@@ -13767,10 +13818,13 @@ function finParseInstructions(text) {
|
|
|
13767
13818
|
if (m) out.lotMult = finInstrNum(m[1] || m[2] || m[3]);
|
|
13768
13819
|
if (out.lotMult != null) out.lotMult = Math.max(1, Math.min(5, out.lotMult));
|
|
13769
13820
|
if (/martingale|mart[ıi]ngale/.test(low)) {
|
|
13770
|
-
/*
|
|
13771
|
-
"martingale çarpanı 1.
|
|
13772
|
-
|
|
13773
|
-
|
|
13821
|
+
/* Faktör serbest: "martingale 1.2", "martingale x1.20", "martingale 1,2",
|
|
13822
|
+
"martingale çarpanı 1.2", "1.2x martingale", "1.2 kat martingale".
|
|
13823
|
+
Yalnız bilinen bağlaçlardan sonra sayı okunur — "martingale kullan, 1R..."
|
|
13824
|
+
gibi metinden yanlış sayı kapmaz. Varsayılan ×2 (1.01–5 arası geçerli). */
|
|
13825
|
+
m = low.match(/(?:mart[ıi]ngale\s*(?:x|×|çarpan[ıi]?|carpan[ıi]?|oran[ıi]?|fakt[öo]r[üu]?|kat[ıi]?)?\s*(\d+(?:[.,]\d+)?))|(?:(\d+(?:[.,]\d+)?)\s*(?:x|×|kat[ıi]?)?\s*mart[ıi]ngale)/);
|
|
13826
|
+
const mf = m ? finInstrNum(m[1] || m[2]) : null;
|
|
13827
|
+
out.martingale = Math.max(1.01, Math.min(5, mf != null && mf > 1 ? mf : 2));
|
|
13774
13828
|
}
|
|
13775
13829
|
/* kısmi kapatma: "1R'de %50" → atR=1, pct=50; "%50 1R" → aynı; "kısmi %50" → atR=1 */
|
|
13776
13830
|
m = low.match(/(\d+(?:[.,]\d+)?)\s*r[^%\d]{0,28}%\s*(\d+(?:[.,]\d+)?)/);
|
|
@@ -13820,6 +13874,11 @@ function finInstrSummary(ins) {
|
|
|
13820
13874
|
if (ins.entry.startBalance != null) p.push(`gün başı ${ins.entry.startBalance}`);
|
|
13821
13875
|
if (ins.entry.dailyLossPct != null) p.push(`günlük zarar limiti %${ins.entry.dailyLossPct}`);
|
|
13822
13876
|
if (ins.manage.partial) p.push(`kısmi %${ins.manage.partial.pct} @${ins.manage.partial.atR}R`);
|
|
13877
|
+
try {
|
|
13878
|
+
const f = finCfg();
|
|
13879
|
+
if (Number(f.maxPositionsNote) > 0) p.push(`maks ${f.maxPositionsNote} pozisyon`);
|
|
13880
|
+
if (Number(f.maxTradesPerDayNote) > 0) p.push(`günde maks ${f.maxTradesPerDayNote} işlem`);
|
|
13881
|
+
} catch {}
|
|
13823
13882
|
return p.join(' · ');
|
|
13824
13883
|
} catch {
|
|
13825
13884
|
return '';
|
|
@@ -14174,6 +14233,66 @@ async function finTsToolRequest(sidS, agent, ans, lines) {
|
|
|
14174
14233
|
const FIN_POSMGR_ID = 'posmanager';
|
|
14175
14234
|
const FIN_POSMGR_AGENT = { main: false, role: '', __posmgr: true };
|
|
14176
14235
|
|
|
14236
|
+
/* Yönetici kontrol sıklığı (sn) — ayarlardan; 1-300 */
|
|
14237
|
+
function finPosMgrSec() {
|
|
14238
|
+
try {
|
|
14239
|
+
return Math.max(1, Math.min(300, Math.round(Number(finCfg().posManagerSec) || 5)));
|
|
14240
|
+
} catch {
|
|
14241
|
+
return 5;
|
|
14242
|
+
}
|
|
14243
|
+
}
|
|
14244
|
+
|
|
14245
|
+
/* KENDİ ZAMANLAYICISI: 1 sn'lik yoklama, ayarlı aralık dolunca turu başlatır —
|
|
14246
|
+
böylece 5 sn'den hızlı (ör. 2 sn) ve yavaş (ör. 60 sn) aralıklar da çalışır.
|
|
14247
|
+
Taze watchdog anlık görüntüsü varsa onu kullanır (ekstra MT5 sorgusu yok). */
|
|
14248
|
+
async function finPosManagerTick() {
|
|
14249
|
+
const pm = financeState.posManager;
|
|
14250
|
+
if (!pm || pm.busy) return;
|
|
14251
|
+
let f = {};
|
|
14252
|
+
try { f = finCfg(); } catch {}
|
|
14253
|
+
if (f.posManagerEnabled === false) return;
|
|
14254
|
+
const sec = finPosMgrSec();
|
|
14255
|
+
if (pm.lastAt && Date.now() - pm.lastAt < sec * 1000) return;
|
|
14256
|
+
if (!mt5bridge.running) return;
|
|
14257
|
+
let positions = null;
|
|
14258
|
+
let account = null;
|
|
14259
|
+
const snap = financeState.posSnapshot;
|
|
14260
|
+
if (snap && Date.now() - Number(snap.at || 0) < 5000) {
|
|
14261
|
+
positions = snap.positions;
|
|
14262
|
+
account = snap.account;
|
|
14263
|
+
} else {
|
|
14264
|
+
try {
|
|
14265
|
+
const [posR, accR] = await Promise.all([
|
|
14266
|
+
mt5bridge.call('positions', {}, 8000).catch(() => null),
|
|
14267
|
+
mt5bridge.call('account', {}, 8000).catch(() => null),
|
|
14268
|
+
]);
|
|
14269
|
+
positions = (posR && posR.ok && posR.data && posR.data.positions) || [];
|
|
14270
|
+
account = (accR && accR.ok && accR.data && accR.data.account) || null;
|
|
14271
|
+
financeState.posSnapshot = { at: Date.now(), positions, account };
|
|
14272
|
+
} catch {
|
|
14273
|
+
return;
|
|
14274
|
+
}
|
|
14275
|
+
}
|
|
14276
|
+
if (!Array.isArray(positions) || !positions.length) {
|
|
14277
|
+
pm.lastPosCount = 0;
|
|
14278
|
+
return;
|
|
14279
|
+
}
|
|
14280
|
+
finPosManagerMaybe(positions, account);
|
|
14281
|
+
}
|
|
14282
|
+
|
|
14283
|
+
function finPosManagerStart() {
|
|
14284
|
+
const pm = financeState.posManager;
|
|
14285
|
+
if (!pm || pm.timer) return;
|
|
14286
|
+
pm.timer = setInterval(() => { finPosManagerTick().catch(() => {}); }, 1000);
|
|
14287
|
+
}
|
|
14288
|
+
|
|
14289
|
+
function finPosManagerStop() {
|
|
14290
|
+
const pm = financeState.posManager;
|
|
14291
|
+
if (!pm || !pm.timer) return;
|
|
14292
|
+
clearInterval(pm.timer);
|
|
14293
|
+
pm.timer = null;
|
|
14294
|
+
}
|
|
14295
|
+
|
|
14177
14296
|
/* Watchdog turundan çağrılır: uygunSA yönetici turunu arka planda başlatır
|
|
14178
14297
|
(MT5 pozisyon verisi watchdog turundan gelir — ikinci sorgu yok). */
|
|
14179
14298
|
function finPosManagerMaybe(positions, account) {
|
|
@@ -14182,6 +14301,8 @@ function finPosManagerMaybe(positions, account) {
|
|
|
14182
14301
|
let f = {};
|
|
14183
14302
|
try { f = finCfg(); } catch {}
|
|
14184
14303
|
if (f.posManagerEnabled === false) return;
|
|
14304
|
+
const sec = finPosMgrSec();
|
|
14305
|
+
if (pm.lastAt && Date.now() - pm.lastAt < sec * 1000) return; /* ayarlı aralık dolmadı */
|
|
14185
14306
|
const list = Array.isArray(positions) ? positions.filter(Boolean) : [];
|
|
14186
14307
|
pm.lastPosCount = list.length;
|
|
14187
14308
|
if (!list.length) return;
|
|
@@ -14349,7 +14470,7 @@ async function finPosManagerRound(positions, account) {
|
|
|
14349
14470
|
finTsPost(
|
|
14350
14471
|
FIN_POSMGR_ID,
|
|
14351
14472
|
FIN_POSMGR_AGENT,
|
|
14352
|
-
`🛡️ Pozisyon yöneticisi turu #${pm.rounds} (LLM yok —
|
|
14473
|
+
`🛡️ Pozisyon yöneticisi turu #${pm.rounds} (LLM yok — ${finPosMgrSec()} sn):\n` +
|
|
14353
14474
|
(instrTxt ? 'TALİMAT AYARLARI (kod uygular): ' + instrTxt + '\n' : '') +
|
|
14354
14475
|
lines.join('\n'),
|
|
14355
14476
|
'yönetim'
|
|
@@ -14661,7 +14782,7 @@ async function finTypeSafeRound(sid, agent) {
|
|
|
14661
14782
|
if (pos) {
|
|
14662
14783
|
/* POZİSYON YÖNETİCİSİ açık: kapat/kısmi/SL kararları onun turunda */
|
|
14663
14784
|
if (posManagerOn) {
|
|
14664
|
-
lines.push(`- ${sym}: pozisyon açık #${pos.ticket} — yönetim Pozisyon Yöneticisi'nde (
|
|
14785
|
+
lines.push(`- ${sym}: pozisyon açık #${pos.ticket} — yönetim Pozisyon Yöneticisi'nde (${finPosMgrSec()} sn Jev turu)`);
|
|
14665
14786
|
continue;
|
|
14666
14787
|
}
|
|
14667
14788
|
const ex = finTsNoul(ans, 'kapat_' + i);
|
|
@@ -14701,9 +14822,10 @@ async function finTypeSafeRound(sid, agent) {
|
|
|
14701
14822
|
}
|
|
14702
14823
|
/* ÇOKLU GİRİŞ: aynı turda birden çok sembol açılabilir — yalnız toplam
|
|
14703
14824
|
slot (pozisyon + bekleyen emir + bu turda açılanlar) tavanı korur */
|
|
14704
|
-
const
|
|
14825
|
+
const posCap = finPosCap(f);
|
|
14826
|
+
const slotsLeft = posCap - pendCount - posList.length - opened;
|
|
14705
14827
|
if (slotsLeft <= 0) {
|
|
14706
|
-
lines.push(`- ${sym}: sinyal güçlü (${c.choice} p=${c.p.toFixed(2)}) ama pozisyon+bekleyen emir sınırı dolu (${posList.length + pendCount}/${
|
|
14828
|
+
lines.push(`- ${sym}: sinyal güçlü (${c.choice} p=${c.p.toFixed(2)}) ama pozisyon+bekleyen emir sınırı dolu (${posList.length + pendCount}/${posCap}) — bu tur açılmadı`);
|
|
14707
14829
|
continue;
|
|
14708
14830
|
}
|
|
14709
14831
|
/* GİRİŞ TİPİ + RİSK PROFİLİ (JEV kararı) — seviyeleri KOD hesaplar */
|
|
@@ -14833,6 +14955,13 @@ async function finTypeSafeRound(sid, agent) {
|
|
|
14833
14955
|
}
|
|
14834
14956
|
/* JEV ARAÇ İSTEĞİ (tur düzeyi): eksik araç varsa TOOL botuna asenkron yazdır */
|
|
14835
14957
|
try { await finTsToolRequest(sidS, agent, ans, lines); } catch {}
|
|
14958
|
+
/* GÖRÜNÜRLÜK: açık pozisyon varken de trade ajanı tur atar ve YENİ
|
|
14959
|
+
girişleri değerlendirir (yönetim ayrı ajanda olsa bile) */
|
|
14960
|
+
if (posManagerOn && posList.length) {
|
|
14961
|
+
lines.unshift(
|
|
14962
|
+
`ℹ️ ${posList.length} açık pozisyon Pozisyon Yöneticisi'nde (${finPosMgrSec()} sn) — bu trade turu yeni girişleri değerlendirdi.`
|
|
14963
|
+
);
|
|
14964
|
+
}
|
|
14836
14965
|
const insTxt = finInstrSummary(ins);
|
|
14837
14966
|
finTsPost(
|
|
14838
14967
|
sidS,
|
|
@@ -15157,6 +15286,7 @@ ipcMain.handle('finance:snapshot', async () => {
|
|
|
15157
15286
|
lastErr: String(financeState.posManager.lastErr || ''),
|
|
15158
15287
|
positions: Number(financeState.posManager.lastPosCount) || 0,
|
|
15159
15288
|
note: String(f.posManagerNote || ''),
|
|
15289
|
+
sec: Number(f.posManagerSec) || 5,
|
|
15160
15290
|
},
|
|
15161
15291
|
};
|
|
15162
15292
|
});
|
|
@@ -15390,6 +15520,7 @@ ipcMain.handle('finance:settings', async (_e, patch) => {
|
|
|
15390
15520
|
/* POZİSYON YÖNETİCİSİ: kendi talimatı + aç/kapa */
|
|
15391
15521
|
if (p.posManagerNote !== undefined) f.posManagerNote = String(p.posManagerNote || '').slice(0, 1500);
|
|
15392
15522
|
if (p.posManagerEnabled !== undefined) f.posManagerEnabled = p.posManagerEnabled !== false;
|
|
15523
|
+
if (p.posManagerSec !== undefined) f.posManagerSec = Math.max(1, Math.min(300, Math.round(Number(p.posManagerSec) || 5)));
|
|
15393
15524
|
if (p.planTime !== undefined) f.planTime = /^([01]?\d|2[0-3]):([0-5]\d)$/.test(String(p.planTime || '').trim()) ? String(p.planTime).trim() : '';
|
|
15394
15525
|
if (p.reviewTime !== undefined) f.reviewTime = /^([01]?\d|2[0-3]):([0-5]\d)$/.test(String(p.reviewTime || '').trim()) ? String(p.reviewTime).trim() : '';
|
|
15395
15526
|
/* TRADE SAATLERİ: {on, start, end} — yerel saat; aralık dışında ajan turları
|
package/src/renderer/index.html
CHANGED
|
@@ -222,10 +222,14 @@
|
|
|
222
222
|
<div class="fin-card" id="finPosCard" data-fin-card="posmgr">
|
|
223
223
|
<div class="fin-card-title">POZİSYON YÖNETİCİSİ <span id="finPosDot" class="fin-dot off" title="Pozisyon yöneticisi durumu"></span><span id="finPosInfo" class="fin-hint"></span></div>
|
|
224
224
|
<div class="fin-field fin-check">
|
|
225
|
-
<label title="Açık pozisyon varken
|
|
226
|
-
<input id="finPosOn" type="checkbox" /> Aktif — açık pozisyonları
|
|
225
|
+
<label title="Açık pozisyon varken ayarlı sıklıkta JEV turu: kapat / kısmi kapat / SL taşı kararları. Trade ajanından bağımsız ayrı bir ajan — kendi talimatıyla çalışır; LLM kullanmaz.">
|
|
226
|
+
<input id="finPosOn" type="checkbox" /> Aktif — açık pozisyonları Jev ile yönet
|
|
227
227
|
</label>
|
|
228
228
|
</div>
|
|
229
|
+
<div class="fin-field">
|
|
230
|
+
<span>Kontrol (sn)</span>
|
|
231
|
+
<input id="finPosSec" type="number" min="1" max="300" step="1" title="Kaç saniyede bir kontrol edilsin — 1-300 (varsayılan 5). Trade ajanından bağımsız kendi zamanlayıcısı vardır." />
|
|
232
|
+
</div>
|
|
229
233
|
<div class="fin-field">
|
|
230
234
|
<span>Yönetici talimatı <i class="fin-hint">— yalnız bu ajanı bağlar</i><button id="finPosHelp" class="fin-help-btn" type="button" title="Neler yazabilirim? Desteklenen talimatlar ve örnekler">?</button></span>
|
|
231
235
|
<textarea id="finPosNote" rows="2" maxlength="1500" placeholder="örn. 1- 1R'de %50 kısmi kapat 2- kâr 2R'ye gelince kalanı kapat 3- zarar -0.5R'yi geçerse kes" title="Bu talimat YALNIZ Pozisyon Yöneticisi Jev ajanına gider (5 sn turu, kapat/kısmi/SL kararları); kaydetmek için alandan çık"></textarea>
|
package/src/renderer/renderer.js
CHANGED
|
@@ -253,6 +253,7 @@ const els = {
|
|
|
253
253
|
finPosDot: $('#finPosDot'),
|
|
254
254
|
finPosInfo: $('#finPosInfo'),
|
|
255
255
|
finPosOn: $('#finPosOn'),
|
|
256
|
+
finPosSec: $('#finPosSec'),
|
|
256
257
|
finPosNote: $('#finPosNote'),
|
|
257
258
|
finPosStatus: $('#finPosStatus'),
|
|
258
259
|
finPosList: $('#finPosList'),
|
|
@@ -9947,6 +9948,7 @@ function finTraderInputsSet(cfg) {
|
|
|
9947
9948
|
if (els.finStrategy && ae !== els.finStrategy && !finStrategyDirty) els.finStrategy.value = cfg.strategy || '';
|
|
9948
9949
|
if (els.finPosNote && ae !== els.finPosNote && !finPosNoteDirty) els.finPosNote.value = cfg.posManagerNote || '';
|
|
9949
9950
|
if (els.finPosOn && ae !== els.finPosOn) els.finPosOn.checked = cfg.posManagerEnabled !== false;
|
|
9951
|
+
if (els.finPosSec && ae !== els.finPosSec) els.finPosSec.value = Number(cfg.posManagerSec) || 5;
|
|
9950
9952
|
if (els.finMaxTradesDay && ae !== els.finMaxTradesDay) els.finMaxTradesDay.value = Number(cfg.maxTradesPerDay) || 0;
|
|
9951
9953
|
if (els.finLossStreak && ae !== els.finLossStreak) els.finLossStreak.value = Number(cfg.lossStreakLimit) || 0;
|
|
9952
9954
|
if (els.finLossStreakPause && ae !== els.finLossStreakPause) els.finLossStreakPause.value = Number(cfg.lossStreakPauseMin) || 0;
|
|
@@ -10113,13 +10115,14 @@ function finRenderPosManager(pm, cfg) {
|
|
|
10113
10115
|
if (!pm) return;
|
|
10114
10116
|
const enabled = cfg ? cfg.posManagerEnabled !== false : pm.enabled !== false;
|
|
10115
10117
|
const pos = Number(pm.positions) || 0;
|
|
10118
|
+
const sec = Number(pm.sec || (cfg && cfg.posManagerSec)) || 5;
|
|
10116
10119
|
if (els.finPosDot) {
|
|
10117
10120
|
els.finPosDot.classList.remove('on', 'off', 'busy');
|
|
10118
10121
|
els.finPosDot.classList.add(!enabled ? 'off' : pm.busy ? 'busy' : pos ? 'on' : 'off');
|
|
10119
10122
|
els.finPosDot.title = !enabled
|
|
10120
10123
|
? 'Pozisyon yöneticisi kapalı'
|
|
10121
10124
|
: pos
|
|
10122
|
-
? 'İzliyor — ' + pos + ' açık pozisyon (
|
|
10125
|
+
? 'İzliyor — ' + pos + ' açık pozisyon (' + sec + ' sn Jev turu)'
|
|
10123
10126
|
: 'Açık pozisyon yok — beklemede';
|
|
10124
10127
|
}
|
|
10125
10128
|
if (els.finPosInfo) els.finPosInfo.textContent = pm.rounds ? '· tur ' + pm.rounds : '';
|
|
@@ -10127,8 +10130,8 @@ function finRenderPosManager(pm, cfg) {
|
|
|
10127
10130
|
let t;
|
|
10128
10131
|
if (!enabled) t = 'Kapalı — kutucuktan aç';
|
|
10129
10132
|
else if (pm.busy) t = 'Tur çalışıyor…';
|
|
10130
|
-
else if (!pos) t = 'Beklemede — açık pozisyon yok';
|
|
10131
|
-
else t = 'İzliyor · ' + pos + ' pozisyon';
|
|
10133
|
+
else if (!pos) t = 'Beklemede — açık pozisyon yok (' + sec + ' sn yoklama)';
|
|
10134
|
+
else t = 'İzliyor · ' + pos + ' pozisyon · ' + sec + ' sn';
|
|
10132
10135
|
if (pm.lastAt) {
|
|
10133
10136
|
const d = new Date(pm.lastAt);
|
|
10134
10137
|
const p = (x) => String(x).padStart(2, '0');
|
|
@@ -10797,6 +10800,7 @@ finAutoNum(els.finMaxTradesDay, 'maxTradesPerDay', 0, 50, 1);
|
|
|
10797
10800
|
finAutoNum(els.finLossStreak, 'lossStreakLimit', 0, 10, 1);
|
|
10798
10801
|
finAutoNum(els.finLossStreakPause, 'lossStreakPauseMin', 0, 1440, 5);
|
|
10799
10802
|
finAutoNum(els.finReentry, 'reentryCooldownMin', 0, 1440, 5);
|
|
10803
|
+
finAutoNum(els.finPosSec, 'posManagerSec', 1, 300, 1);
|
|
10800
10804
|
finAutoNum(els.finMaxPerCurrency, 'maxPerCurrency', 0, 20, 1);
|
|
10801
10805
|
const finTimeSave = (el, key) => {
|
|
10802
10806
|
if (!el) return;
|
|
@@ -10934,8 +10938,8 @@ function finHelpHtml(which) {
|
|
|
10934
10938
|
'<b>Kod otomatik uygular.</b> Girişler %2 risk ile açılır (kalibrasyon çarpanı devre dışı, 0.1-10 arası).'],
|
|
10935
10939
|
['<code>lot x1.5</code><code>poz başı lot 1.5</code><code>lotu 2 kat yap</code>',
|
|
10936
10940
|
'<b>Kod otomatik uygular.</b> Tüm giriş riskine/lotuna çarpan.'],
|
|
10937
|
-
['<code>martingale</code><code>martingale 1.
|
|
10938
|
-
'<b>Kod otomatik uygular.</b> Kayıp serisinde lot katlanır (
|
|
10941
|
+
['<code>martingale</code><code>martingale 1.2</code><code>martingale x1.20</code><code>1.2 kat martingale</code>',
|
|
10942
|
+
'<b>Kod otomatik uygular.</b> Kayıp serisinde lot katlanır — faktör serbest (ör. 1.2). Varsayılan ×2; 1.01–5 arası geçerli, seri en çok ×3, toplam risk tavanı %10 ve max lot kilidi geçerli.'],
|
|
10939
10943
|
['<code>her mumda işlem açmak zorundasın</code><code>her barda işlem</code><code>her zaman işlem</code>',
|
|
10940
10944
|
'<b>ZORUNLU GİRİŞ modu.</b> "bekle" seçeneği kaldırılır, eşik/teyit kapıları atlanır, emir market olur. "zorunlu değil" yazarsan mod açılmaz.'],
|
|
10941
10945
|
['<code>M1</code><code>1m</code><code>5 dk</code><code>4 saat</code>',
|
|
@@ -10944,12 +10948,14 @@ function finHelpHtml(which) {
|
|
|
10944
10948
|
'Gün başı bakiyesi — her turda günlük K/Z otomatik hesaplanır ve Jev\'e durum olarak verilir.'],
|
|
10945
10949
|
['<code>günlük zarar %3</code><code>max günlük kayıp 3</code>',
|
|
10946
10950
|
'<b>Kod otomatik uygular.</b> Limit aşılırsa yeni işlem açılmaz; günlük kayıp otomasyonunun limiti bu olur.'],
|
|
10951
|
+
['<code>aynı anda en fazla 10 işlem</code><code>en fazla 10 pozisyon</code><code>günde en fazla 10 işlem</code>',
|
|
10952
|
+
'<b>Kod otomatik uygular.</b> Eşzamanlı tavan (pozisyon + bekleyen emir) ya da günlük işlem tavanı. Talimatta yazdığın sürece Ayarlar\'daki değeri ezer; metinden kaldırınca ayar geçerli olur.'],
|
|
10947
10953
|
];
|
|
10948
10954
|
const example = posmgr
|
|
10949
10955
|
? `1- 1R'de %50 kısmi kapat\n2- kâr 2R'ye gelince kalanı kapat\n3- zarar -0.5R'yi geçerse kes`
|
|
10950
|
-
: `1- risk yüzde 2\n2- martingale kullan (
|
|
10956
|
+
: `1- risk yüzde 2\n2- martingale kullan (x1.2)\n3- her mumda işlem açmak zorundasın\n4- aynı anda en fazla 10 işlem\n5- başlangıç bakiye 10.000\n6- günlük zarar %3`;
|
|
10951
10957
|
const head = posmgr
|
|
10952
|
-
? 'Pozisyon Yöneticisi (5 sn
|
|
10958
|
+
? 'Pozisyon Yöneticisi (ayarlı sıklık — varsayılan 5 sn) açık pozisyonları yönetir: kapat / kısmi kapat / SL taşı. Trade Ajanı pozisyon açıkken de tur atmaya devam eder ve yeni girişleri değerlendirir.'
|
|
10953
10959
|
: 'Trade Ajanı girişleri yönetir: yön, emir tipi, risk, lot, martingale ve günlük limitler.';
|
|
10954
10960
|
const rows = items
|
|
10955
10961
|
.map((it) => '<div class="fin-help-item"><div class="fin-help-code">' + it[0] + '</div><div class="fin-help-desc">' + it[1] + '</div></div>')
|