Skip to content

Commit 2d03002

Browse files
committed
Merge branch 'dev' into 'main'
fix(hybrid): cap resting BUY orders at Active orders window See merge request AndreyPopov/spot-trading-bot!56
2 parents ea2b064 + aa4965e commit 2d03002

2 files changed

Lines changed: 36 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@
66

77
- Hybrid tail now follows price like the micro: at placement it takes the live micro's price when that is more favorable than its own recomputed exit, and while resting it recomputes on every poll and cancel-replaces on drift — so lowering Micro profit %/commission reaches an already-placed tail immediately instead of only on the next fill that deepens the ladder.
88

9+
### Fixed
10+
11+
- A role-less classic close left resting on the hybrid tail's slot (the ladder deepened past it without it ever yielding) blocked the tail from ever being placed there — it now gets adopted, diffed against the recomputed tail price/quantity, and cancel-replaced on drift like any other tail.
12+
- The adopted leftover close above only got tagged with role `'tail'` when a price drift triggered a `cancelReplace`; a leftover that already matched the recomputed price stayed untagged forever, so its eventual fill fell into the classic whole-position `DONE` path while the carrying rung (with its own live micro) was still held, ending the cycle early. Untagged leftovers are now stamped with role `'tail'` as pure bookkeeping, no exchange call.
13+
- Telegram's Start message could report auto-restart as off even when the saved grid had it on — the Start socket call never forwarded the flag, so it read a stale `false` instead of the grid file's own `restart` value.
14+
915
## v2.0.7
1016

1117
### Added

src/modules/jsonTimerSender.js

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -851,7 +851,36 @@ class JsonTimerSender extends EventEmitter {
851851
cellStatus === 'PARTIALLY_FILLED'
852852
) {
853853
if (i === parseFloat(obj['param']['field-activeOrders'])) {
854-
return;
854+
// Beyond the active-orders window: a resting order here is pulled so
855+
// exactly N stay active, instead of sitting unmanaged (unseen by this
856+
// loop at all) until the cycle's final cleanup. A not-yet-placed slot
857+
// (status null) has nothing to cancel — skipped outright, since
858+
// falling through to job[method] below would place it early.
859+
if (
860+
val.orderId != null &&
861+
!val.manual &&
862+
(cellStatus === 'NEW' || cellStatus === 'PARTIALLY_FILLED')
863+
) {
864+
const res = await this.#runToApi({
865+
method: 'cancelOrder',
866+
data: { id: key, symbol: this.symbol, orderId: val.orderId },
867+
});
868+
if (res && res.success !== false) {
869+
val.status = 'CANCELED';
870+
if (res.message?.executedQty !== undefined) {
871+
val.executedQty = parseFloat(res.message.executedQty) || 0;
872+
val.cummulativeQuoteQty = parseFloat(res.message.cummulativeQuoteQty) || 0;
873+
}
874+
logBus.log(
875+
`🔁 ${this.symbol}: ${strategy.side} #${key + 1} @ ${val.price} pulled — ` +
876+
`beyond the ${i}-wide active-orders window`
877+
);
878+
obj.date_modified = new Date().toISOString();
879+
await this.#mergeLiveEdits(obj);
880+
await writeFileAtomic(this.#filePath(), JSON.stringify(obj, null, 2));
881+
}
882+
}
883+
continue;
855884
}
856885
i++;
857886
}

0 commit comments

Comments
 (0)