Smoke test: closing legs without quantity, the stop-first fallback, and a 22 s hold before closing
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
6876223fa4
commit
59af95f0b1
@@ -193,17 +193,27 @@ if (CONFIRM && ORDER_ACCOUNT) {
|
|||||||
const px = pos.openPrice;
|
const px = pos.openPrice;
|
||||||
const tick = inst.priceIncrement || 0.01;
|
const tick = inst.priceIncrement || 0.01;
|
||||||
const far = (p) => Math.round(p / tick) * tick;
|
const far = (p) => Math.round(p / tick) * tick;
|
||||||
|
// Exactly what lib/dxtrade-class.ts sends: a closing STOP/LIMIT names
|
||||||
|
// the position, never a quantity (code 33 otherwise).
|
||||||
const leg = (c, type, price) => ({
|
const leg = (c, type, price) => ({
|
||||||
account: ORDER_ACCOUNT, orderCode: c, type, instrument: symbol, quantity: pos.quantity, positionEffect: 'CLOSE',
|
account: ORDER_ACCOUNT, orderCode: c, type, instrument: symbol, positionEffect: 'CLOSE',
|
||||||
positionCode: pos.positionCode, side: 'SELL', tif: 'GTC', ...(type === 'LIMIT' ? { limitPrice: price } : { stopPrice: price }),
|
positionCode: pos.positionCode, side: 'SELL', tif: 'GTC', ...(type === 'LIMIT' ? { limitPrice: price } : { stopPrice: price }),
|
||||||
});
|
});
|
||||||
const group = await call('POST', `/accounts/${acct}/orders`, {
|
const group = await call('POST', `/accounts/${acct}/orders`, {
|
||||||
body: { orders: [leg(`${code}-tp`, 'LIMIT', far(px * 1.05)), leg(`${code}-sl`, 'STOP', far(px * 0.95))], contingencyType: 'OCO' },
|
body: { orders: [leg(`${code}-tp`, 'LIMIT', far(px * 1.05)), leg(`${code}-sl`, 'STOP', far(px * 0.95))], contingencyType: 'OCO' },
|
||||||
});
|
});
|
||||||
show(`native OCO group of CLOSE legs (HTTP ${group.status})`, group.data);
|
show(`native OCO group of CLOSE legs (HTTP ${group.status})`, group.data);
|
||||||
show('open orders now', (await call('GET', `/accounts/${acct}/orders`)).data);
|
if (group.status >= 400) {
|
||||||
|
// The bot's fallback: the stop on its own first, then the take-profit.
|
||||||
|
show('fallback: lone STOP CLOSE', (await call('POST', `/accounts/${acct}/orders`, { body: leg(`${code}-sl1`, 'STOP', far(px * 0.95)) })));
|
||||||
|
show('fallback: lone LIMIT CLOSE', (await call('POST', `/accounts/${acct}/orders`, { body: leg(`${code}-tp1`, 'LIMIT', far(px * 1.05)) })));
|
||||||
|
}
|
||||||
|
show('open orders now (the exit pair should be here)', (await call('GET', `/accounts/${acct}/orders`)).data);
|
||||||
const del = await call('DELETE', `/accounts/${acct}/orders/${encodeURIComponent(`${code}-tp`)}`);
|
const del = await call('DELETE', `/accounts/${acct}/orders/${encodeURIComponent(`${code}-tp`)}`);
|
||||||
show(`cancel without If-Match (HTTP ${del.status}; 403/412/428 means it wants one)`, del.data);
|
show(`cancel without If-Match (HTTP ${del.status}; 403/412/428 means it wants one)`, del.data);
|
||||||
|
// Tradeify: every trade must be held at least 20 seconds.
|
||||||
|
console.log('holding 22 s before closing (minimum hold)…');
|
||||||
|
await sleep(22_000);
|
||||||
const flatten = await call('POST', `/accounts/${acct}/close`, { body: { account: ORDER_ACCOUNT, closePositions: true, cancelOrders: true } });
|
const flatten = await call('POST', `/accounts/${acct}/close`, { body: { account: ORDER_ACCOUNT, closePositions: true, cancelOrders: true } });
|
||||||
show(`flatten via /close (HTTP ${flatten.status})`, flatten.data);
|
show(`flatten via /close (HTTP ${flatten.status})`, flatten.data);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user