Drain and extra-day legs always trade MNQ
They traded the micro of whatever the firm listed: MNQ with NQ, but MGC for a firm listing only GC and CL. Now every futures firm's tiny legs go on MNQ, the one micro the bot has always drained on. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
5696f2b036
commit
ed62788480
@@ -122,8 +122,7 @@ the batch firm's list, at random but weighted:
|
||||
the type's max contracts); an instrument whose expected hold for the
|
||||
batch's leg is 12 h or more is out of the draw (e.g. 6E at a $1,000 leg,
|
||||
about a week).
|
||||
- Micros stay out of the draw; drain and extra-day legs trade the micro of a
|
||||
listed product (MNQ when NQ is listed).
|
||||
- Micros stay out of the draw; drain and extra-day legs always trade MNQ.
|
||||
|
||||
Every draw logs its odds. `GET /api/instruments` shows each firm's list with
|
||||
spread, daily move, hold and chance (`?simulate=10000` runs the real draw
|
||||
|
||||
+2
-2
@@ -23,7 +23,7 @@ import {
|
||||
} from './trading-logic';
|
||||
import { getSetting, setSetting } from './db';
|
||||
import type { LaneTick, TickReason } from './master-protocol';
|
||||
import { POINT_VALUES, housekeepingRoot, MAX_HOLD_HOURS } from './instrument-specs';
|
||||
import { POINT_VALUES, housekeepingRoot, HOUSEKEEPING_ROOT, MAX_HOLD_HOURS } from './instrument-specs';
|
||||
import { firmInstruments, drawFuturesInstrument, spreadBlock, type LegShape } from './instruments';
|
||||
import { recordEntry } from './trade-mix';
|
||||
import { errorMessage, isClientReady, isOrderNotPlaced, type PlatformClient, type PlatformContract, type PickContext } from './platform-client';
|
||||
@@ -434,7 +434,7 @@ function releaseTradeMutex(lease: number, lane: string): void {
|
||||
* housekeepingRoot); a DXtrade firm its current pick. */
|
||||
function housekeepingFor(firm: { platform: string; instruments?: string[]; bannedSymbols?: string[]; symbolMap?: Record<string, { symbol: string }[]> }): string {
|
||||
if (firm.platform === 'dxtrade') return '*';
|
||||
return housekeepingRoot(firmInstruments(firm)) ?? 'MNQ';
|
||||
return housekeepingRoot(firmInstruments(firm)) ?? HOUSEKEEPING_ROOT;
|
||||
}
|
||||
|
||||
/** The instrument a leg actually trades: drain legs go on the firm's
|
||||
|
||||
+7
-12
@@ -227,21 +227,16 @@ export function pickByChance(chances: { symbol: string; chance: number }[], rand
|
||||
return chances.length > 0 ? chances[chances.length - 1].symbol : null;
|
||||
}
|
||||
|
||||
/** What every futures firm's drain and extra-day legs trade. */
|
||||
export const HOUSEKEEPING_ROOT = 'MNQ';
|
||||
|
||||
/**
|
||||
* What a firm's drain and extra-day legs trade — tiny, so a micro: MNQ when
|
||||
* NQ or MNQ is listed (as always), else the micro of a listed full-size
|
||||
* contract, else a listed micro, else the listed root with the smallest tick
|
||||
* value. null for an empty list.
|
||||
* What a firm's drain and extra-day legs trade: always MNQ — tiny targets
|
||||
* belong on a micro, whatever the firm lists for its full-size legs. null
|
||||
* for an empty list: that firm trades nothing.
|
||||
*/
|
||||
export function housekeepingRoot(listed: readonly string[]): string | null {
|
||||
const roots = listed.filter((r) => CME_SPECS[r]);
|
||||
if (roots.length === 0) return null;
|
||||
if (roots.includes('NQ') || roots.includes('MNQ')) return 'MNQ';
|
||||
const twin = roots.find((r) => MICRO_OF[r]);
|
||||
if (twin) return MICRO_OF[twin];
|
||||
const micro = roots.find((r) => CME_SPECS[r].micro);
|
||||
if (micro) return micro;
|
||||
return [...roots].sort((a, b) => tickValue(a) - tickValue(b))[0];
|
||||
return listed.some((r) => CME_SPECS[r]) ? HOUSEKEEPING_ROOT : null;
|
||||
}
|
||||
|
||||
const DXTRADE_SYMBOL = /^[A-Za-z0-9./_:-]{1,32}$/;
|
||||
|
||||
@@ -140,12 +140,13 @@ test('10k seeded draws land on the chances', () => {
|
||||
assert.equal(pickByChance([], 0.5), null);
|
||||
});
|
||||
|
||||
test('drain and extra-day legs: a micro of what is listed', () => {
|
||||
test('drain and extra-day legs: always MNQ', () => {
|
||||
// Always MNQ, whatever the firm lists; nothing for a firm that lists nothing.
|
||||
assert.equal(housekeepingRoot(['NQ', 'GC', 'CL', '6E']), 'MNQ');
|
||||
assert.equal(housekeepingRoot(['MNQ']), 'MNQ');
|
||||
assert.equal(housekeepingRoot(['GC', 'CL']), 'MGC');
|
||||
assert.equal(housekeepingRoot(['6E', 'ZN']), '6E'); // no micro: the smallest tick value
|
||||
assert.equal(housekeepingRoot(['MCL', 'ZB']), 'MCL');
|
||||
assert.equal(housekeepingRoot(['GC', 'CL']), 'MNQ');
|
||||
assert.equal(housekeepingRoot(['6E', 'ZN']), 'MNQ');
|
||||
assert.equal(housekeepingRoot(['MCL', 'ZB']), 'MNQ');
|
||||
assert.equal(housekeepingRoot([]), null);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user