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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "beast-agent",
3
3
  "productName": "Beast Agent",
4
- "version": "2.74.0",
4
+ "version": "2.76.0",
5
5
  "description": "Ultra-fast local agent shell for Windows.",
6
6
  "author": "algokodcom (AlgoKod)",
7
7
  "license": "MIT",
@@ -802,7 +802,8 @@ const handlers = {
802
802
  }
803
803
  const pos = await bcall('positions', {}, 8000);
804
804
  const list = (pos && pos.positions) || [];
805
- const maxPos = Number(cfg.maxPositions) || 3;
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
- return finrisk.disciplineError(finJournalTail(400), Date.now(), finCfg(), side, symbol, positions);
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): açık pozisyon varken 5 sn'lik tur aynı anda
11628
- yönetici karar turunu tetikler (ayrı MT5 sorgusu yok; meşgulse atlar) */
11629
- if (positionsOk && positions.length) {
11630
- try { finPosManagerMaybe(positions, account); } catch {}
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) return;
11647
- financeState.watchTimer = setInterval(() => { finWatchTick().catch(() => {}); }, 5000);
11648
- finWatchTick().catch(() => {});
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
- /* faktör yalnız bitişik yazımdan okunur: "martingale 1.5", "martingale x2",
13771
- "martingale çarpanı 1.5" — "martingale kullan, 1R..." gibi metinden sayı kapmaz */
13772
- m = low.match(/mart[ıi]ngale\s*(?:x|×|çarpan[ıi]?|carpan[ıi]?)?\s*(\d+(?:[.,]\d+)?)/);
13773
- out.martingale = m ? Math.max(1.1, Math.min(5, finInstrNum(m[1]) || 2)) : 2;
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 — 5 sn):\n` +
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 (5 sn Jev turu)`);
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 slotsLeft = (Number(f.maxPositions) || 3) - pendCount - posList.length - opened;
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}/${Number(f.maxPositions) || 3}) — bu tur açılmadı`);
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ı
@@ -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 5 saniyede bir 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ı 5 sn'de bir Jev ile yönet
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>
@@ -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 (5 sn Jev turu)'
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.5</code><code>martingale x2</code>',
10938
- '<b>Kod otomatik uygular.</b> Kayıp serisinde lot katlanır (varsayılan ×2; seri en çok ×3, toplam risk tavanı %10 ve max lot kilidi geçerli).'],
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 (x2)\n3- her mumda işlem açmak zorundasın\n4- başlangıç bakiye 10.000\n5- günlük zarar %3`;
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 turu) açık pozisyonları yönetir: kapat / kısmi kapat / SL taşı.'
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>')