beast-agent 2.30.1 → 2.30.2
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 +10 -2
- package/src/renderer/index.html +21 -11
- package/src/renderer/renderer.js +34 -64
- package/src/renderer/style.css +49 -6
package/package.json
CHANGED
package/src/main.js
CHANGED
|
@@ -8323,8 +8323,12 @@ function finCfg() {
|
|
|
8323
8323
|
/* OTOMATİK İŞLEM hep açık — kullanıcı onay kutusu KALDIRILDI: trade ajanının
|
|
8324
8324
|
amacı zaten işlem açmak; onay sorulmaz, limitler (max lot/pozisyon) korur */
|
|
8325
8325
|
f.allowTrading = true;
|
|
8326
|
-
|
|
8327
|
-
|
|
8326
|
+
/* ANALİZ EKİBİ ARTIK SADECE SAYI: elle rol seçimi kaldırıldı — atama daima
|
|
8327
|
+
otomatik (Teknik → Risk → Haber). 0 = ekip kapalı GEÇERLİ değerdir;
|
|
8328
|
+
yalnız eksik/bozuk değerde varsayılan 2'ye düşülür. */
|
|
8329
|
+
f.analysisAuto = true;
|
|
8330
|
+
if (!Number.isFinite(Number(f.analysisCount))) f.analysisCount = 2;
|
|
8331
|
+
f.analysisCount = Math.max(0, Math.min(FIN_ROLES_AUTO.length, Math.round(Number(f.analysisCount) || 0)));
|
|
8328
8332
|
if (!Number(f.intervalSec)) f.intervalSec = 120;
|
|
8329
8333
|
if (!Number(f.maxLot)) f.maxLot = 0.1;
|
|
8330
8334
|
if (f.maxPositions == null) f.maxPositions = 3;
|
|
@@ -8767,6 +8771,7 @@ ipcMain.handle('finance:snapshot', async () => {
|
|
|
8767
8771
|
let account = st.account || null;
|
|
8768
8772
|
let positions = [];
|
|
8769
8773
|
let orders = [];
|
|
8774
|
+
let ordersError = '';
|
|
8770
8775
|
let symbols = [];
|
|
8771
8776
|
if (st.running) {
|
|
8772
8777
|
const [a, p, o, sy] = await Promise.all([
|
|
@@ -8778,6 +8783,7 @@ ipcMain.handle('finance:snapshot', async () => {
|
|
|
8778
8783
|
if (a && a.ok) account = a.data && a.data.account;
|
|
8779
8784
|
if (p && p.ok) positions = (p.data && p.data.positions) || [];
|
|
8780
8785
|
if (o && o.ok) orders = (o.data && o.data.orders) || [];
|
|
8786
|
+
else if (o && o.error) ordersError = String(o.error).slice(0, 200);
|
|
8781
8787
|
if (sy && sy.ok) symbols = (sy.data && sy.data.symbols) || [];
|
|
8782
8788
|
}
|
|
8783
8789
|
const busy = financeState.traderSid && engine ? engine.isBusy(financeState.traderSid) : false;
|
|
@@ -8787,9 +8793,11 @@ ipcMain.handle('finance:snapshot', async () => {
|
|
|
8787
8793
|
account,
|
|
8788
8794
|
positions,
|
|
8789
8795
|
orders,
|
|
8796
|
+
ordersError,
|
|
8790
8797
|
symbols,
|
|
8791
8798
|
cfg: f,
|
|
8792
8799
|
roles: FIN_ROLES,
|
|
8800
|
+
rolesAuto: FIN_ROLES_AUTO,
|
|
8793
8801
|
trader: { on: financeState.traderOn, busy, rounds: financeState.traderRounds, lastAt: financeState.lastRoundAt },
|
|
8794
8802
|
};
|
|
8795
8803
|
});
|
package/src/renderer/index.html
CHANGED
|
@@ -163,15 +163,27 @@
|
|
|
163
163
|
</div>
|
|
164
164
|
<div class="fin-card fin-card-trader">
|
|
165
165
|
<div class="fin-card-title">TRADE AJANI <span id="finTraderDot" class="fin-dot off" title="Trader durumu"></span></div>
|
|
166
|
-
<div class="fin-
|
|
167
|
-
|
|
168
|
-
<
|
|
169
|
-
<label>Max lot</label><input id="finMaxLot" type="number" min="0.01" max="100" step="0.01" />
|
|
166
|
+
<div class="fin-field">
|
|
167
|
+
<span>Model</span>
|
|
168
|
+
<select id="finTraderModel" title="Trader ajanının modeli — farklı API/model seçilebilir"></select>
|
|
170
169
|
</div>
|
|
171
|
-
<div class="fin-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
170
|
+
<div class="fin-grid2">
|
|
171
|
+
<div class="fin-field">
|
|
172
|
+
<span>Tur (sn)</span>
|
|
173
|
+
<input id="finInterval" type="number" min="30" max="3600" step="10" />
|
|
174
|
+
</div>
|
|
175
|
+
<div class="fin-field">
|
|
176
|
+
<span>Max lot</span>
|
|
177
|
+
<input id="finMaxLot" type="number" min="0.01" max="100" step="0.01" />
|
|
178
|
+
</div>
|
|
179
|
+
</div>
|
|
180
|
+
<div class="fin-field">
|
|
181
|
+
<span>Semboller</span>
|
|
182
|
+
<button id="finSymBtn" class="fin-sym-select" title="MT5 sembol listesinden seç — tıkla">…</button>
|
|
183
|
+
</div>
|
|
184
|
+
<div class="fin-field">
|
|
185
|
+
<span>Analiz ekibi <i class="fin-hint">— sadece sayı seç, rolleri sistem otomatik atar</i></span>
|
|
186
|
+
<div id="finRoles" class="fin-roles" title="Trader'ın yanında koşacak uzman ajan SAYISI — roller otomatik atanır (Teknik → Risk → Haber); işlem açmazlar"></div>
|
|
175
187
|
</div>
|
|
176
188
|
<div class="fin-row fin-btn-row">
|
|
177
189
|
<button id="finTraderBtn" class="fin-start">▶︎ Ajanı Başlat</button>
|
|
@@ -181,9 +193,7 @@
|
|
|
181
193
|
<div class="fin-card">
|
|
182
194
|
<div class="fin-card-title">POZİSYONLAR <span id="finPosCount"></span></div>
|
|
183
195
|
<div id="finPosList"><div class="fin-empty">Açık pozisyon yok</div></div>
|
|
184
|
-
|
|
185
|
-
<div class="fin-card">
|
|
186
|
-
<div class="fin-card-title">BEKLEYEN EMİRLER <span id="finOrdCount"></span></div>
|
|
196
|
+
<div class="fin-sect-title">BEKLEYEN EMİRLER <span id="finOrdCount"></span></div>
|
|
187
197
|
<div id="finOrdList"><div class="fin-empty">Bekleyen emir yok</div></div>
|
|
188
198
|
</div>
|
|
189
199
|
<div class="fin-card">
|
package/src/renderer/renderer.js
CHANGED
|
@@ -8888,14 +8888,14 @@ const FIN_ORDER_TYPES = {
|
|
|
8888
8888
|
7: { t: 'SELL STP-LMT', c: 'sell' },
|
|
8889
8889
|
};
|
|
8890
8890
|
|
|
8891
|
-
function finRenderOrders(list) {
|
|
8891
|
+
function finRenderOrders(list, err) {
|
|
8892
8892
|
if (!els.finOrdList) return;
|
|
8893
8893
|
els.finOrdList.textContent = '';
|
|
8894
8894
|
if (els.finOrdCount) els.finOrdCount.textContent = list && list.length ? '(' + list.length + ')' : '';
|
|
8895
8895
|
if (!list || !list.length) {
|
|
8896
8896
|
const d = document.createElement('div');
|
|
8897
8897
|
d.className = 'fin-empty';
|
|
8898
|
-
d.textContent = 'Bekleyen emir yok';
|
|
8898
|
+
d.textContent = err ? 'Emir listesi alınamadı: ' + err : 'Bekleyen emir yok';
|
|
8899
8899
|
els.finOrdList.appendChild(d);
|
|
8900
8900
|
return;
|
|
8901
8901
|
}
|
|
@@ -8994,89 +8994,60 @@ function finTraderInputsSet(cfg) {
|
|
|
8994
8994
|
if (els.finTraderModel && ae !== els.finTraderModel && cfg.traderSel) els.finTraderModel.value = cfg.traderSel;
|
|
8995
8995
|
}
|
|
8996
8996
|
|
|
8997
|
-
/* ANALİZ EKİBİ:
|
|
8998
|
-
(
|
|
8999
|
-
|
|
9000
|
-
Katalog sunucudan (finance snapshot/state.roles) gelir, yerel yedek var. */
|
|
8997
|
+
/* ANALİZ EKİBİ: SADECE SAYI seçilir — rolleri sistem otomatik atar
|
|
8998
|
+
(FIN_ROLES_AUTO sırası: Teknik → Risk → Haber). Elle rol kutucukları
|
|
8999
|
+
kaldırıldı; analysisAuto sunucuda daima açık. Katalog sunucudan gelir. */
|
|
9001
9000
|
let finRolesCatalog = [
|
|
9002
9001
|
{ id: 'risk', label: 'Risk Ajanı', desc: 'marj/kaldıraç/SL disiplini, exposure ve günlük kayıp hızı denetimi' },
|
|
9003
9002
|
{ id: 'technic', label: 'Teknik Analiz', desc: 'trend/yapı/destek-direnç/momentum okuma, AL-SAT-BEKLE önerileri' },
|
|
9004
9003
|
{ id: 'macro', label: 'Haber / Makro', desc: 'haber akışı + ekonomik takvim, DXY/emtia bağıntıları, yön eğilimi' },
|
|
9005
9004
|
];
|
|
9005
|
+
let finRolesAuto = ['technic', 'risk', 'macro'];
|
|
9006
9006
|
let finRolesDirty = false; /* tık→kaydet arası snapshot ezmesin */
|
|
9007
9007
|
let finRolesSyncTimer = null;
|
|
9008
9008
|
|
|
9009
|
-
function
|
|
9010
|
-
const
|
|
9011
|
-
return
|
|
9009
|
+
function finRoleLabel(id) {
|
|
9010
|
+
const d = (finRolesCatalog || []).find((x) => x.id === String(id || ''));
|
|
9011
|
+
return d ? d.label : String(id || '');
|
|
9012
9012
|
}
|
|
9013
9013
|
|
|
9014
9014
|
function finRenderRoles(cfg) {
|
|
9015
9015
|
const box = els.finRoles;
|
|
9016
9016
|
if (!box) return;
|
|
9017
9017
|
if (finRolesDirty) return; /* bekleyen kullanıcı değişikliği korunur */
|
|
9018
|
-
const
|
|
9019
|
-
const count = Math.max(0, Math.round(Number(cfg && cfg.analysisCount) || 0));
|
|
9020
|
-
const sel = cfg && Array.isArray(cfg.analysisTeam) ? cfg.analysisTeam : [];
|
|
9018
|
+
const max = Math.max(1, (finRolesAuto || []).length || 3);
|
|
9019
|
+
const count = Math.max(0, Math.min(max, Math.round(Number(cfg && cfg.analysisCount) || 0)));
|
|
9021
9020
|
box.innerHTML = '';
|
|
9022
|
-
|
|
9023
|
-
|
|
9024
|
-
const autoLab = document.createElement('label');
|
|
9025
|
-
autoLab.className = 'fin-role fin-role-auto';
|
|
9026
|
-
autoLab.title = 'Rol seçmeden SAYI gir — gereklı ajanları sistem otomatik atar (teknik → risk → haber sırası)';
|
|
9027
|
-
const autoCb = document.createElement('input');
|
|
9028
|
-
autoCb.type = 'checkbox';
|
|
9029
|
-
autoCb.checked = auto;
|
|
9030
|
-
autoLab.appendChild(autoCb);
|
|
9031
|
-
autoLab.appendChild(document.createTextNode('⚙ Otomatik'));
|
|
9032
|
-
autoCb.addEventListener('change', () => {
|
|
9033
|
-
finRolesDirty = true;
|
|
9034
|
-
finSaveCfg({ analysisAuto: autoCb.checked });
|
|
9035
|
-
toast(autoCb.checked ? 'Analiz ekibi OTOMATİK — sayı kadar gereklı ajan atanır' : 'Analiz ekibi ELLE SEÇİM moduna geçti');
|
|
9036
|
-
clearTimeout(finRolesSyncTimer);
|
|
9037
|
-
finRolesSyncTimer = setTimeout(() => { finRolesDirty = false; finSnapshot(); }, 900);
|
|
9038
|
-
});
|
|
9039
|
-
box.appendChild(autoLab);
|
|
9040
|
-
|
|
9021
|
+
const wrap = document.createElement('div');
|
|
9022
|
+
wrap.className = 'fin-team';
|
|
9041
9023
|
const cnt = document.createElement('input');
|
|
9042
9024
|
cnt.type = 'number';
|
|
9043
9025
|
cnt.className = 'fin-role-count';
|
|
9044
9026
|
cnt.min = '0';
|
|
9045
|
-
cnt.max = String(
|
|
9027
|
+
cnt.max = String(max);
|
|
9046
9028
|
cnt.step = '1';
|
|
9047
|
-
cnt.value = String(count
|
|
9048
|
-
cnt.title = '
|
|
9049
|
-
|
|
9029
|
+
cnt.value = String(count);
|
|
9030
|
+
cnt.title = 'Kaç uzman ajan koşacak (0 = ekip yok, en fazla ' + max + '). Roller otomatik atanır.';
|
|
9031
|
+
const hint = document.createElement('span');
|
|
9032
|
+
hint.className = 'fin-team-hint';
|
|
9033
|
+
const names = (n) => finRolesAuto.slice(0, n).map(finRoleLabel);
|
|
9034
|
+
const paint = (n) => {
|
|
9035
|
+
hint.textContent = n > 0 ? 'otomatik: ' + names(n).join(' · ') : 'ekip kapalı — sadece trader koşar';
|
|
9036
|
+
};
|
|
9050
9037
|
cnt.addEventListener('change', () => {
|
|
9038
|
+
const n = Math.max(0, Math.min(max, Math.round(Number(cnt.value) || 0)));
|
|
9039
|
+
cnt.value = String(n);
|
|
9051
9040
|
finRolesDirty = true;
|
|
9052
|
-
finSaveCfg({
|
|
9053
|
-
|
|
9041
|
+
finSaveCfg({ analysisAuto: true, analysisCount: n });
|
|
9042
|
+
paint(n);
|
|
9043
|
+
toast(n ? 'Analiz ekibi: ' + n + ' ajan — ' + names(n).join(', ') : 'Analiz ekibi kapatıldı');
|
|
9054
9044
|
clearTimeout(finRolesSyncTimer);
|
|
9055
9045
|
finRolesSyncTimer = setTimeout(() => { finRolesDirty = false; finSnapshot(); }, 900);
|
|
9056
9046
|
});
|
|
9057
|
-
|
|
9058
|
-
|
|
9059
|
-
|
|
9060
|
-
|
|
9061
|
-
const lab = document.createElement('label');
|
|
9062
|
-
lab.className = 'fin-role';
|
|
9063
|
-
const cb = document.createElement('input');
|
|
9064
|
-
cb.type = 'checkbox';
|
|
9065
|
-
cb.dataset.role = r.id;
|
|
9066
|
-
cb.checked = sel.includes(r.id);
|
|
9067
|
-
cb.disabled = auto;
|
|
9068
|
-
cb.title = r.desc + ' — tüm skill + mt5 erişimli, işlem açmaz';
|
|
9069
|
-
lab.appendChild(cb);
|
|
9070
|
-
lab.appendChild(document.createTextNode(r.label));
|
|
9071
|
-
cb.addEventListener('change', () => {
|
|
9072
|
-
finRolesDirty = true;
|
|
9073
|
-
finSaveCfg({ analysisTeam: finRolesSel() });
|
|
9074
|
-
toast(r.label + (cb.checked ? ' ekibe eklendi — sonraki başlatışta koşar' : ' ekipten çıkarıldı'));
|
|
9075
|
-
clearTimeout(finRolesSyncTimer);
|
|
9076
|
-
finRolesSyncTimer = setTimeout(() => { finRolesDirty = false; finSnapshot(); }, 900);
|
|
9077
|
-
});
|
|
9078
|
-
box.appendChild(lab);
|
|
9079
|
-
}
|
|
9047
|
+
paint(count);
|
|
9048
|
+
wrap.appendChild(cnt);
|
|
9049
|
+
wrap.appendChild(hint);
|
|
9050
|
+
box.appendChild(wrap);
|
|
9080
9051
|
}
|
|
9081
9052
|
|
|
9082
9053
|
function finRenderTrader(trader, cfg) {
|
|
@@ -9141,9 +9112,10 @@ async function finSnapshot() {
|
|
|
9141
9112
|
finSetDot(b.connected ? true : b.running ? 'busy' : false, b);
|
|
9142
9113
|
finRenderAccount(r.account);
|
|
9143
9114
|
finRenderPositions(r.positions || []);
|
|
9144
|
-
finRenderOrders(r.orders || []);
|
|
9115
|
+
finRenderOrders(r.orders || [], r.ordersError || '');
|
|
9145
9116
|
finRenderSymbols(r.symbols || []);
|
|
9146
9117
|
if (Array.isArray(r.roles) && r.roles.length) finRolesCatalog = r.roles;
|
|
9118
|
+
if (Array.isArray(r.rolesAuto) && r.rolesAuto.length) finRolesAuto = r.rolesAuto;
|
|
9147
9119
|
finTraderInputsSet(r.cfg);
|
|
9148
9120
|
finRenderRoles(r.cfg);
|
|
9149
9121
|
finRenderTrader(r.trader, r.cfg);
|
|
@@ -9258,9 +9230,7 @@ if (els.finTraderBtn) {
|
|
|
9258
9230
|
else if (r && r.ok) {
|
|
9259
9231
|
const cfg = (await beast.financeState().catch(() => null));
|
|
9260
9232
|
const c = (cfg && cfg.cfg) || {};
|
|
9261
|
-
const team = c.
|
|
9262
|
-
? Math.round(Number(c.analysisCount) || 0)
|
|
9263
|
-
: finRolesSel().length;
|
|
9233
|
+
const team = Math.round(Number(c.analysisCount) || 0);
|
|
9264
9234
|
toast(team ? 'Trade ajanı + analiz ekibi (' + team + ' uzman) başladı — turlar panelde izlenir' : 'Trade ajanı başladı — turlar panelde izlenir');
|
|
9265
9235
|
}
|
|
9266
9236
|
}
|
package/src/renderer/style.css
CHANGED
|
@@ -4833,6 +4833,49 @@ body.finance-mode #composerWrap { margin-right: var(--finW, 400px); }
|
|
|
4833
4833
|
}
|
|
4834
4834
|
.fin-row input:focus, .fin-row select:focus { border-color: var(--accent); outline: none; }
|
|
4835
4835
|
|
|
4836
|
+
/* TRADE AJANI formu — etiket üstte, kontrol altta; tur/max lot 2 kolon */
|
|
4837
|
+
.fin-field { display: flex; flex-direction: column; gap: 3px; min-width: 0; margin-bottom: 8px; }
|
|
4838
|
+
.fin-field > span { font-size: 10px; color: var(--muted); }
|
|
4839
|
+
.fin-field input, .fin-field select {
|
|
4840
|
+
width: 100%;
|
|
4841
|
+
min-width: 0;
|
|
4842
|
+
background: var(--panel2);
|
|
4843
|
+
border: 1px solid var(--border);
|
|
4844
|
+
color: var(--text);
|
|
4845
|
+
font-size: 12px;
|
|
4846
|
+
padding: 4px 7px;
|
|
4847
|
+
border-radius: 6px;
|
|
4848
|
+
}
|
|
4849
|
+
.fin-field input:focus, .fin-field select:focus { border-color: var(--accent); outline: none; }
|
|
4850
|
+
.fin-field .fin-sym-select { width: 100%; }
|
|
4851
|
+
.fin-grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
|
|
4852
|
+
.fin-grid2 .fin-field { margin-bottom: 8px; }
|
|
4853
|
+
.fin-hint { font-style: normal; opacity: 0.75; }
|
|
4854
|
+
/* ekib sayısı + otomatik atama özeti */
|
|
4855
|
+
.fin-team { display: flex; align-items: center; gap: 8px; min-width: 0; }
|
|
4856
|
+
.fin-team-hint {
|
|
4857
|
+
flex: 1;
|
|
4858
|
+
min-width: 0;
|
|
4859
|
+
font-size: 10.5px;
|
|
4860
|
+
color: var(--muted);
|
|
4861
|
+
white-space: nowrap;
|
|
4862
|
+
overflow: hidden;
|
|
4863
|
+
text-overflow: ellipsis;
|
|
4864
|
+
}
|
|
4865
|
+
/* POZİSYONLAR kartı içi bölüm başlığı (bekleyen emirler) */
|
|
4866
|
+
.fin-sect-title {
|
|
4867
|
+
display: flex;
|
|
4868
|
+
align-items: center;
|
|
4869
|
+
gap: 6px;
|
|
4870
|
+
margin: 9px 0 6px;
|
|
4871
|
+
padding-top: 8px;
|
|
4872
|
+
border-top: 1px dashed var(--border);
|
|
4873
|
+
font-size: 10px;
|
|
4874
|
+
font-weight: 800;
|
|
4875
|
+
letter-spacing: 1px;
|
|
4876
|
+
color: var(--muted);
|
|
4877
|
+
}
|
|
4878
|
+
|
|
4836
4879
|
/* TRADE AJANI sembol seçme düğmesi — tıklayınca MT5 sembol seçici açılır */
|
|
4837
4880
|
.fin-sym-select {
|
|
4838
4881
|
flex: 1;
|
|
@@ -4887,15 +4930,15 @@ body.finance-mode #composerWrap { margin-right: var(--finW, 400px); }
|
|
|
4887
4930
|
.fin-role input:disabled { opacity: 0.45; cursor: default; }
|
|
4888
4931
|
.fin-role-auto { font-weight: 700; }
|
|
4889
4932
|
/* Otomatik moddaki SAYI girişi */
|
|
4890
|
-
.fin-role-count {
|
|
4891
|
-
flex: none; width:
|
|
4933
|
+
.fin-field .fin-role-count {
|
|
4934
|
+
flex: none; width: 52px;
|
|
4892
4935
|
background: var(--panel2); color: var(--text);
|
|
4893
4936
|
border: 1px solid var(--border); border-radius: 8px;
|
|
4894
|
-
font-size:
|
|
4895
|
-
padding:
|
|
4937
|
+
font-size: 12px; font-weight: 700; text-align: center;
|
|
4938
|
+
padding: 3px 3px;
|
|
4896
4939
|
}
|
|
4897
|
-
.fin-role-count:focus { border-color: var(--accent); outline: none; }
|
|
4898
|
-
.fin-role-count:disabled { opacity: 0.45; }
|
|
4940
|
+
.fin-field .fin-role-count:focus { border-color: var(--accent); outline: none; }
|
|
4941
|
+
.fin-field .fin-role-count:disabled { opacity: 0.45; }
|
|
4899
4942
|
.fin-start {
|
|
4900
4943
|
flex: none;
|
|
4901
4944
|
background: var(--accent);
|