beast-agent 2.76.4 → 2.76.6
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/main.js +118 -28
- package/src/preload.js +1 -0
- package/src/renderer/index.html +2 -2
- package/src/renderer/renderer.js +22 -1
package/package.json
CHANGED
package/src/main.js
CHANGED
|
@@ -10006,16 +10006,10 @@ function finCfg() {
|
|
|
10006
10006
|
finNormalizeSymbolLimits(f);
|
|
10007
10007
|
if (f.maxPositions == null) f.maxPositions = 3;
|
|
10008
10008
|
/* KODLA DİSİPLİN (trader kuralları): hepsi 0 = kural kapalı */
|
|
10009
|
-
/* GÜNLÜK İŞLEM LİMİTİ KALDIRILDI
|
|
10010
|
-
|
|
10011
|
-
|
|
10012
|
-
|
|
10013
|
-
if (!Number.isFinite(Number(f.maxTradesPerDay))) f.maxTradesPerDay = 0;
|
|
10014
|
-
if (f.maxTradesPerDayDefaultCleared !== true) {
|
|
10015
|
-
f.maxTradesPerDayDefaultCleared = true;
|
|
10016
|
-
if (Number(f.maxTradesPerDay) === 10) f.maxTradesPerDay = 0;
|
|
10017
|
-
try { saveSettings(); } catch {}
|
|
10018
|
-
}
|
|
10009
|
+
/* GÜNLÜK İŞLEM LİMİTİ TAMAMEN KALDIRILDI: ayar değeri artık uygulanmaz
|
|
10010
|
+
(0'a sabitlenir). Günlük limit YALNIZ talimata "günde en fazla N işlem"
|
|
10011
|
+
yazılırsa (not) devreye girer — varsayılan SINIRSIZ. */
|
|
10012
|
+
f.maxTradesPerDay = 0;
|
|
10019
10013
|
if (!Number.isFinite(Number(f.lossStreakLimit))) f.lossStreakLimit = 2;
|
|
10020
10014
|
if (!Number.isFinite(Number(f.lossStreakPauseMin))) f.lossStreakPauseMin = 30;
|
|
10021
10015
|
/* RE-ENTRY BEKLEME: kural VARSAYILAN KAPALI (0) — isteyen Gelişmiş
|
|
@@ -10422,18 +10416,18 @@ function finTeamDigest() {
|
|
|
10422
10416
|
function finDisciplineError(side, symbol, positions) {
|
|
10423
10417
|
try {
|
|
10424
10418
|
const cfg = finCfg();
|
|
10425
|
-
/* TALİMAT
|
|
10426
|
-
|
|
10427
|
-
|
|
10428
|
-
|
|
10429
|
-
|
|
10430
|
-
|
|
10431
|
-
|
|
10432
|
-
|
|
10433
|
-
|
|
10434
|
-
|
|
10435
|
-
|
|
10436
|
-
|
|
10419
|
+
/* GÜNLÜK İŞLEM LİMİTİ: yalnız TALİMAT notu uygulanır ("günde en fazla N
|
|
10420
|
+
işlem"); ayarlardaki değer KALDIRILDI. Not yoksa kural kapalı = sınırsız
|
|
10421
|
+
(günlük işlem sayısı asla yeni girişi engellemez). */
|
|
10422
|
+
const dayNote = Number(cfg.maxTradesPerDayNote) > 0 ? Number(cfg.maxTradesPerDayNote) : 0;
|
|
10423
|
+
return finrisk.disciplineError(
|
|
10424
|
+
finJournalTail(400),
|
|
10425
|
+
Date.now(),
|
|
10426
|
+
{ ...cfg, maxTradesPerDay: dayNote },
|
|
10427
|
+
side,
|
|
10428
|
+
symbol,
|
|
10429
|
+
positions
|
|
10430
|
+
);
|
|
10437
10431
|
} catch {
|
|
10438
10432
|
return null;
|
|
10439
10433
|
}
|
|
@@ -10932,23 +10926,42 @@ async function finStopAllFinanceAgents(reason) {
|
|
|
10932
10926
|
return sids.length;
|
|
10933
10927
|
}
|
|
10934
10928
|
|
|
10935
|
-
/* Tüm açık pozisyonları kapatır (
|
|
10936
|
-
|
|
10929
|
+
/* Tüm açık pozisyonları kapatır (TOPLU KAPATMA).
|
|
10930
|
+
reason: 'risk' (günlük limit flatten) | 'manuel' (panel butonu) |
|
|
10931
|
+
'kural' (talimat kâr hedefi — "karda tümünü kapat" gibi).
|
|
10932
|
+
opts.withPending: bekleyen emirler de iptal edilir (yeni pozisyon açılmasın). */
|
|
10933
|
+
async function finFlattenAll(reason, opts) {
|
|
10937
10934
|
if (financeState.flattening) return 0;
|
|
10938
10935
|
if (!mt5bridge.running) return 0;
|
|
10936
|
+
const why = ['risk', 'manuel', 'kural'].includes(String(reason)) ? String(reason) : 'risk';
|
|
10939
10937
|
financeState.flattening = true;
|
|
10940
10938
|
let closed = 0;
|
|
10941
10939
|
try {
|
|
10940
|
+
/* ÖNCE bekleyen emirler (ops.): kapanırken yeni pozisyon aktifleşmesin */
|
|
10941
|
+
if (opts && opts.withPending) {
|
|
10942
|
+
try {
|
|
10943
|
+
const o = await mt5bridge.call('orders', {}, 10000);
|
|
10944
|
+
const orders = (o && o.ok && o.data && o.data.orders) || [];
|
|
10945
|
+
for (const ord of orders) {
|
|
10946
|
+
await mt5bridge.call('cancel', { ticket: ord.ticket }, 10000).catch(() => null);
|
|
10947
|
+
}
|
|
10948
|
+
if (orders.length) financeLog('[toplu] ' + orders.length + ' bekleyen emir iptal edildi');
|
|
10949
|
+
} catch {}
|
|
10950
|
+
}
|
|
10942
10951
|
const r = await mt5bridge.call('positions', {}, 10000);
|
|
10943
10952
|
const list = (r && r.ok && r.data && r.data.positions) || [];
|
|
10944
10953
|
for (const p of list) {
|
|
10945
10954
|
const cr = await mt5bridge.call('close', { ticket: p.ticket, volume: 0 }, 15000).catch(() => null);
|
|
10946
10955
|
if (cr && cr.ok) closed++;
|
|
10947
10956
|
}
|
|
10948
|
-
const line =
|
|
10949
|
-
|
|
10950
|
-
|
|
10951
|
-
|
|
10957
|
+
const line = why === 'manuel'
|
|
10958
|
+
? `🧯 Toplu kapatma (panel): ${closed}/${list.length} pozisyon kapatıldı`
|
|
10959
|
+
: why === 'kural'
|
|
10960
|
+
? `🎯 Toplu kapatma (kâr hedefi): ${closed}/${list.length} pozisyon kapatıldı`
|
|
10961
|
+
: `🚨 Günlük limit: ${closed}/${list.length} pozisyon kapatıldı`;
|
|
10962
|
+
financeLog('[' + why + '] ' + line);
|
|
10963
|
+
financeNotify(line, why === 'risk' ? 'risk' : 'close');
|
|
10964
|
+
finJournal({ kind: why === 'risk' ? 'risk-flatten' : 'close-all', why, closed, total: list.length });
|
|
10952
10965
|
finStatsRefresh(true).catch(() => {});
|
|
10953
10966
|
} finally {
|
|
10954
10967
|
financeState.flattening = false;
|
|
@@ -10956,6 +10969,34 @@ async function finFlattenAll() {
|
|
|
10956
10969
|
return closed;
|
|
10957
10970
|
}
|
|
10958
10971
|
|
|
10972
|
+
/* TOPLU KAPATMA KURALI (talimat): "karda tümünü kapat" / "toplam kâr %2 olunca
|
|
10973
|
+
hepsini kapat" / "50 dolar kârda tümünü kapat" → sepet (tüm pozisyonların
|
|
10974
|
+
toplam yüzen K/Z'si) hedefe ulaşınca HEPSİ kapatılır. Kural yoksa no-op. */
|
|
10975
|
+
async function finBasketCloseCheck(positions, account) {
|
|
10976
|
+
const rule = finParsedInstr().manage.closeAllProfit;
|
|
10977
|
+
if (!rule) return;
|
|
10978
|
+
if (financeState.flattening) return;
|
|
10979
|
+
const list = Array.isArray(positions) ? positions.filter(Boolean) : [];
|
|
10980
|
+
if (!list.length) return;
|
|
10981
|
+
const total = Math.round(list.reduce((a, p) => a + (Number(p.profit) || 0), 0) * 100) / 100;
|
|
10982
|
+
const bal = Number(account && account.balance) || 0;
|
|
10983
|
+
let hit = false;
|
|
10984
|
+
if (rule.money != null) hit = total >= Number(rule.money);
|
|
10985
|
+
else if (rule.pct != null && bal > 0) hit = total >= (bal * Number(rule.pct)) / 100;
|
|
10986
|
+
else hit = total > 0; /* "karda tümünü kapat" → herhangi bir net kâr */
|
|
10987
|
+
if (!hit) return;
|
|
10988
|
+
const closed = await finFlattenAll('kural', { withPending: true });
|
|
10989
|
+
if (closed > 0) {
|
|
10990
|
+
financeNotify(`🎯 Toplu kapatma kuralı: sepet +${total} → ${closed} pozisyon kapatıldı`, 'close');
|
|
10991
|
+
finWakeAgents(
|
|
10992
|
+
`[FİNANS OLAYI — TOPLU KAPATMA] Talimat kâr hedefi tetiklendi: tüm pozisyonların toplamı +${total} (hedef ` +
|
|
10993
|
+
(rule.money != null ? rule.money : rule.pct != null ? '%' + rule.pct : 'kâr') +
|
|
10994
|
+
') → tüm pozisyonlar kapatıldı. Hesabı ve yeni planı değerlendir.',
|
|
10995
|
+
{ kind: 'close-all', total }
|
|
10996
|
+
);
|
|
10997
|
+
}
|
|
10998
|
+
}
|
|
10999
|
+
|
|
10959
11000
|
/* ---- performans istatistikleri (kalıcı) ---- */
|
|
10960
11001
|
function finStatsLoad() {
|
|
10961
11002
|
const s = finReadJson(finFile('stats.json'), null);
|
|
@@ -11726,6 +11767,10 @@ async function finWatchTick() {
|
|
|
11726
11767
|
if (positions.length) {
|
|
11727
11768
|
try { finPosManagerMaybe(positions, account); } catch {}
|
|
11728
11769
|
}
|
|
11770
|
+
/* TOPLU KAPATMA KURALI: talimat kâr hedefi (sepet) dolduysa hepsini kapat */
|
|
11771
|
+
if (positions.length) {
|
|
11772
|
+
try { await finBasketCloseCheck(positions, account); } catch {}
|
|
11773
|
+
}
|
|
11729
11774
|
}
|
|
11730
11775
|
try { await finCheckAlerts(); } catch {}
|
|
11731
11776
|
if (!financeState.lastStatsAt || Date.now() - financeState.lastStatsAt > 120000) {
|
|
@@ -13973,6 +14018,31 @@ function finParseInstructions(text) {
|
|
|
13973
14018
|
) {
|
|
13974
14019
|
out.noLossClose = true;
|
|
13975
14020
|
}
|
|
14021
|
+
/* TOPLU KAPATMA (kâr hedefi): "karda tümünü kapat", "toplam kâr %2 olunca
|
|
14022
|
+
hepsini kapat", "50 dolar kârda tümünü kapat" → sepet (tüm pozisyonların
|
|
14023
|
+
toplam yüzen K/Z'si) hedefe ulaşınca HEPSİ kapatılır (kod uygular).
|
|
14024
|
+
Zarar hedefli panik kapatma bilinçli olarak KAPSAM DIŞI. */
|
|
14025
|
+
{
|
|
14026
|
+
const allClose =
|
|
14027
|
+
/(?:t[üu]m[üu]n[üu](?:\s*pozisyonlar[ıi]?)?|hepsini|t[üu]m\s*pozisyonlar[ıi]?|toplu(?:\s*kapatma)?)[^.\n]{0,30}?kapat/.test(low);
|
|
14028
|
+
if (allClose && /k[âa]r/.test(low)) {
|
|
14029
|
+
let pct = null;
|
|
14030
|
+
let money = null;
|
|
14031
|
+
let mm = low.match(/k[âa]r[^0-9%]{0,16}%\s*(\d+(?:[.,]\d+)?)/) ||
|
|
14032
|
+
low.match(/toplam[^0-9%]{0,16}%\s*(\d+(?:[.,]\d+)?)[^.\n]{0,16}?k[âa]r/);
|
|
14033
|
+
if (mm) pct = finInstrNum(mm[1]);
|
|
14034
|
+
if (pct == null) {
|
|
14035
|
+
mm = low.match(/(\d+(?:[.,]\d+)?)\s*(?:dolar|usd|\$)[^.\n]{0,16}?k[âa]r/) ||
|
|
14036
|
+
low.match(/k[âa]r[^0-9]{0,16}\$?\s*(\d+(?:[.,]\d+)?)/);
|
|
14037
|
+
if (mm) money = finInstrNum(mm[1]);
|
|
14038
|
+
}
|
|
14039
|
+
out.closeAllProfit = {
|
|
14040
|
+
pct: pct != null && pct > 0 ? Math.min(50, pct) : null,
|
|
14041
|
+
money: pct == null && money != null && money > 0 ? money : null,
|
|
14042
|
+
any: pct == null && money == null,
|
|
14043
|
+
};
|
|
14044
|
+
}
|
|
14045
|
+
}
|
|
13976
14046
|
return out;
|
|
13977
14047
|
}
|
|
13978
14048
|
|
|
@@ -13993,6 +14063,8 @@ function finParsedInstr() {
|
|
|
13993
14063
|
partial: mgr.partial || trade.partial,
|
|
13994
14064
|
/* YÖNETİM KURALI: zararda kapatma yasağı iki nottan birinde varsa geçerli */
|
|
13995
14065
|
noLossClose: !!(mgr.noLossClose || trade.noLossClose),
|
|
14066
|
+
/* TOPLU KAPATMA kâr hedefi (iki nottan biri) */
|
|
14067
|
+
closeAllProfit: mgr.closeAllProfit || trade.closeAllProfit || null,
|
|
13996
14068
|
},
|
|
13997
14069
|
};
|
|
13998
14070
|
}
|
|
@@ -14008,6 +14080,10 @@ function finInstrSummary(ins) {
|
|
|
14008
14080
|
if (ins.entry.dailyLossPct != null) p.push(`günlük zarar limiti %${ins.entry.dailyLossPct}`);
|
|
14009
14081
|
if (ins.manage.partial) p.push(`kısmi %${ins.manage.partial.pct} @${ins.manage.partial.atR}R (yalnız kârda)`);
|
|
14010
14082
|
if (ins.manage.noLossClose) p.push('zararda kapatma YOK');
|
|
14083
|
+
if (ins.manage.closeAllProfit) {
|
|
14084
|
+
const r = ins.manage.closeAllProfit;
|
|
14085
|
+
p.push(r.money != null ? `toplu kapatma +${r.money}` : r.pct != null ? `toplu kapatma +%${r.pct}` : 'kârda toplu kapatma');
|
|
14086
|
+
}
|
|
14011
14087
|
try {
|
|
14012
14088
|
const f = finCfg();
|
|
14013
14089
|
if (Number(f.maxPositionsNote) > 0) p.push(`maks ${f.maxPositionsNote} pozisyon`);
|
|
@@ -14516,6 +14592,12 @@ async function finPosManagerRound(positions, account) {
|
|
|
14516
14592
|
kapatma_kurali: ins.manage.noLossClose
|
|
14517
14593
|
? 'ZARARDA KAPATMA YOK (kod uygular): zarardaki pozisyonun kapatma kararı reddedilir — SL/TP kapatması serbest; kısmi kapatma YALNIZ kârda'
|
|
14518
14594
|
: 'zararda kapatma serbest',
|
|
14595
|
+
/* SEPET: tüm pozisyonların toplam yüzen K/Z'si — toplu kapatma kuralı
|
|
14596
|
+
ve "tümünü kapat" kararı bu veriyle verilir */
|
|
14597
|
+
sepet_kz: Math.round(positions.reduce((a, p) => a + (Number(p.profit) || 0), 0) * 100) / 100,
|
|
14598
|
+
toplu_kapatma: ins.manage.closeAllProfit
|
|
14599
|
+
? 'KURAL: sepet kâr hedefine ulaşınca TÜMÜ kapatılır (kod uygular; panelde "Tümünü Kapat" da var)'
|
|
14600
|
+
: '',
|
|
14519
14601
|
talimat_ayarlari: instrTxt || '(sayısal kural yok)',
|
|
14520
14602
|
gun_durumu: (() => {
|
|
14521
14603
|
try {
|
|
@@ -15914,6 +15996,14 @@ ipcMain.handle('finance:close', async (_e, payload) => {
|
|
|
15914
15996
|
return r;
|
|
15915
15997
|
});
|
|
15916
15998
|
|
|
15999
|
+
/* TOPLU KAPATMA (panel butonu): tüm açık pozisyonlar + bekleyen emirler kapanır */
|
|
16000
|
+
ipcMain.handle('finance:closeAll', async () => {
|
|
16001
|
+
if (!mt5bridge.running) return { ok: false, error: 'MT5 köprüsü bağlı değil' };
|
|
16002
|
+
const closed = await finFlattenAll('manuel', { withPending: true });
|
|
16003
|
+
finPush('trade', { line: 'TOPLU KAPATMA (panel): ' + closed + ' pozisyon kapatıldı' });
|
|
16004
|
+
return { ok: true, closed };
|
|
16005
|
+
});
|
|
16006
|
+
|
|
15917
16007
|
/* Bekleyen emri panelden iptal et (ajanın mt5_cancel aracıyla aynı köprü) */
|
|
15918
16008
|
ipcMain.handle('finance:cancel', async (_e, payload) => {
|
|
15919
16009
|
const ticket = Number(payload && payload.ticket);
|
package/src/preload.js
CHANGED
|
@@ -130,6 +130,7 @@ contextBridge.exposeInMainWorld('beast', {
|
|
|
130
130
|
financeAgentSpawn: (symbol) => ipcRenderer.invoke('finance:agent:spawn', { symbol }),
|
|
131
131
|
financeConnect: () => ipcRenderer.invoke('finance:connect'),
|
|
132
132
|
financeClose: (ticket, volume) => ipcRenderer.invoke('finance:close', { ticket, volume }),
|
|
133
|
+
financeCloseAll: () => ipcRenderer.invoke('finance:closeAll'),
|
|
133
134
|
financeCancel: (ticket) => ipcRenderer.invoke('finance:cancel', { ticket }),
|
|
134
135
|
financeInstall: () => ipcRenderer.invoke('finance:install'),
|
|
135
136
|
financeMt5Setup: () => ipcRenderer.invoke('finance:mt5:setup'),
|
package/src/renderer/index.html
CHANGED
|
@@ -200,7 +200,7 @@
|
|
|
200
200
|
<div class="fin-field">
|
|
201
201
|
<span>Disiplin <i class="fin-hint">— kodla zorlanır; 0 = kural kapalı</i></span>
|
|
202
202
|
<div class="fin-grid2">
|
|
203
|
-
<div class="fin-field"><span>Günlük max işlem</span><input id="finMaxTradesDay" type="number" min="0" max="50" step="1" title="
|
|
203
|
+
<div class="fin-field"><span>Günlük max işlem (kapalı)</span><input id="finMaxTradesDay" type="number" min="0" max="50" step="1" disabled title="Kaldırıldı: günlük işlem limiti yalnız talimata "günde en fazla N işlem" yazarsan uygulanır — varsayılan sınırsız" /></div>
|
|
204
204
|
<div class="fin-field"><span>Kayıp serisi limiti</span><input id="finLossStreak" type="number" min="0" max="10" step="1" title="Üst üste bu kadar kayıptan sonra yeni işlem kilidi (0 = kapalı)" /></div>
|
|
205
205
|
<div class="fin-field"><span>Seri molası (dk)</span><input id="finLossStreakPause" type="number" min="0" max="1440" step="5" title="Kayıp serisi limitine ulaşınca kaç dakika yeni işlem açılmaz" /></div>
|
|
206
206
|
<div class="fin-field"><span>Re-entry bekleme (dk)</span><input id="finReentry" type="number" min="0" max="1440" step="5" title="Aynı sembolda bir işlem kapandıktan sonra yeni giriş için beklenecek süre — VARSAYILAN KAPALI (0 = kapalı)" /></div>
|
|
@@ -300,7 +300,7 @@
|
|
|
300
300
|
</div>
|
|
301
301
|
</div>
|
|
302
302
|
<div class="fin-card" data-fin-card="positions">
|
|
303
|
-
<div class="fin-card-title">POZİSYONLAR <span id="finPosCount"></span></div>
|
|
303
|
+
<div class="fin-card-title">POZİSYONLAR <span id="finPosCount"></span><span class="file-spacer"></span><button id="finCloseAll" title="TOPLU KAPATMA — tüm açık pozisyonları ve bekleyen emirleri kapat">Tümünü Kapat</button></div>
|
|
304
304
|
<div id="finPosList"><div class="fin-empty">Açık pozisyon yok</div></div>
|
|
305
305
|
<div class="fin-sect-title">BEKLEYEN EMİRLER <span id="finOrdCount"></span></div>
|
|
306
306
|
<div id="finOrdList"><div class="fin-empty">Bekleyen emir yok</div></div>
|
package/src/renderer/renderer.js
CHANGED
|
@@ -258,6 +258,7 @@ const els = {
|
|
|
258
258
|
finPosStatus: $('#finPosStatus'),
|
|
259
259
|
finPosList: $('#finPosList'),
|
|
260
260
|
finPosCount: $('#finPosCount'),
|
|
261
|
+
finCloseAll: $('#finCloseAll'),
|
|
261
262
|
finOrdList: $('#finOrdList'),
|
|
262
263
|
finOrdCount: $('#finOrdCount'),
|
|
263
264
|
finSymList: $('#finSymList'),
|
|
@@ -9780,6 +9781,8 @@ function finRenderPositions(list) {
|
|
|
9780
9781
|
if (!els.finPosList) return;
|
|
9781
9782
|
els.finPosList.textContent = '';
|
|
9782
9783
|
if (els.finPosCount) els.finPosCount.textContent = list && list.length ? '(' + list.length + ')' : '';
|
|
9784
|
+
/* toplu kapatma butonu: pozisyon yoksa pasif */
|
|
9785
|
+
if (els.finCloseAll) els.finCloseAll.disabled = !(list && list.length);
|
|
9783
9786
|
if (!list || !list.length) {
|
|
9784
9787
|
const d = document.createElement('div');
|
|
9785
9788
|
d.className = 'fin-empty';
|
|
@@ -10949,13 +10952,15 @@ function finHelpHtml(which) {
|
|
|
10949
10952
|
['<code>günlük zarar %3</code><code>max günlük kayıp 3</code>',
|
|
10950
10953
|
'<b>Kod otomatik uygular.</b> Limit aşılırsa yeni işlem açılmaz; günlük kayıp otomasyonunun limiti bu olur.'],
|
|
10951
10954
|
['<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> "aynı anda/en fazla pozisyon" = eşzamanlı tavan (pozisyon + bekleyen emir). <b>Günlük işlem limiti varsayılan
|
|
10955
|
+
'<b>Kod otomatik uygular.</b> "aynı anda/en fazla pozisyon" = eşzamanlı tavan (pozisyon + bekleyen emir). <b>Günlük işlem limiti kaldırıldı (varsayılan sınırsız)</b>; yalnız "günde en fazla N işlem" yazarsan o gün için devreye girer — Ayarlar\'daki günlük limit alanı artık kullanılmıyor.'],
|
|
10953
10956
|
['<code>sembol başına 5 işlem</code><code>aynı sembolde en fazla 3 pozisyon</code>',
|
|
10954
10957
|
'<b>Kod otomatik uygular.</b> Aynı sembolde çoklu işlem tavanı (toplam tavanı aşamaz). Toplam tavan yazarsan ("aynı anda en fazla 10 işlem") aynı sembolde de o tavana kadar işlem açılabilir; yazmazsan Ayarlar → maks/pay değeri geçerlidir.'],
|
|
10955
10958
|
['<code>zararda işlem kapatma</code><code>sadece karda kapat</code><code>kârda değilse kapatma</code>',
|
|
10956
10959
|
'<b>Kod otomatik uygular.</b> Zarardaki pozisyonun kapatma kararı REDDEDİLİR — SL/TP çalışmaya devam eder (stop = martingale serisinin parçası). Kârdaki/başabaştaki pozisyon normal kapatılır.'],
|
|
10957
10960
|
['<code>0.5R karda yarısını kapat</code><code>partial close ile yarısını kapat</code>',
|
|
10958
10961
|
'<b>Kod otomatik uygular.</b> Kâr +0.5R\'ye ulaşınca pozisyonun %50\'si kapatılır — <b>yalnız kârdayken</b> uygulanır (zararda kısmi stop yapılmaz).'],
|
|
10962
|
+
['<code>karda tümünü kapat</code><code>toplam kâr %2 olunca hepsini kapat</code><code>50 dolar kârda tümünü kapat</code>',
|
|
10963
|
+
'<b>Kod otomatik uygular (TOPLU KAPATMA).</b> Tüm pozisyonların toplamı hedefe ulaşınca (herhangi bir kâr / +%X / +X dolar) HEPSİ + bekleyen emirler kapatılır. Panelde POZİSYONLAR başlığındaki <b>Tümünü Kapat</b> butonuyla elle de yapılabilir.'],
|
|
10959
10964
|
];
|
|
10960
10965
|
const example = posmgr
|
|
10961
10966
|
? `1- 1R'de %50 kısmi kapat\n2- kâr 2R'ye gelince kalanı kapat\n3- zarar -0.5R'yi geçerse kes`
|
|
@@ -11707,6 +11712,22 @@ if (els.finLearnClear) {
|
|
|
11707
11712
|
}
|
|
11708
11713
|
|
|
11709
11714
|
if (els.finSymAdd) els.finSymAdd.addEventListener('click', finSymPickerOpen);
|
|
11715
|
+
/* TOPLU KAPATMA: tüm pozisyonlar + bekleyen emirler tek onayla kapanır */
|
|
11716
|
+
if (els.finCloseAll) {
|
|
11717
|
+
els.finCloseAll.addEventListener('click', async () => {
|
|
11718
|
+
const ok = await uiConfirm(
|
|
11719
|
+
'TÜM açık pozisyonlar ve bekleyen emirler kapatılsın mı?\n(TOPLU KAPATMA — geri alınamaz)',
|
|
11720
|
+
'Tümünü Kapat',
|
|
11721
|
+
'Vazgeç'
|
|
11722
|
+
);
|
|
11723
|
+
if (!ok) return;
|
|
11724
|
+
els.finCloseAll.disabled = true;
|
|
11725
|
+
const r = await beast.financeCloseAll().catch((e) => ({ ok: false, error: String((e && e.message) || e) }));
|
|
11726
|
+
if (r && r.ok) toast('Toplu kapatma: ' + (Number(r.closed) || 0) + ' pozisyon kapatıldı');
|
|
11727
|
+
else toast('Toplu kapatma başarısız: ' + ((r && r.error) || '?'));
|
|
11728
|
+
finSnapshot();
|
|
11729
|
+
});
|
|
11730
|
+
}
|
|
11710
11731
|
if (els.finWatchClear) {
|
|
11711
11732
|
els.finWatchClear.addEventListener('click', async () => {
|
|
11712
11733
|
if (!finWatch.length) {
|