@adaptic/utils 0.0.1013 → 0.0.1014
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/dist/index.cjs +488 -77
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +485 -78
- package/dist/index.mjs.map +1 -1
- package/dist/test.js.map +1 -1
- package/dist/types/__tests__/alpaca-broker-error-preservation.test.d.ts +2 -0
- package/dist/types/__tests__/alpaca-broker-error-preservation.test.d.ts.map +1 -0
- package/dist/types/__tests__/technical-analysis-totality.test.d.ts +2 -0
- package/dist/types/__tests__/technical-analysis-totality.test.d.ts.map +1 -0
- package/dist/types/alpaca/index.d.ts.map +1 -1
- package/dist/types/alpaca/legacy/orders.d.ts.map +1 -1
- package/dist/types/alpaca/trading/orders.d.ts.map +1 -1
- package/dist/types/alpaca/trading/trailing-stops.d.ts.map +1 -1
- package/dist/types/alpaca-trading-api.d.ts.map +1 -1
- package/dist/types/errors/index.d.ts +149 -1
- package/dist/types/errors/index.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/schemas/massive-schemas.d.ts +6 -6
- package/dist/types/technical-analysis.d.ts +25 -0
- package/dist/types/technical-analysis.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -2210,11 +2210,20 @@ class AdapticUtilsError extends Error {
|
|
|
2210
2210
|
*/
|
|
2211
2211
|
class AlpacaApiError extends AdapticUtilsError {
|
|
2212
2212
|
statusCode;
|
|
2213
|
-
|
|
2213
|
+
brokerError;
|
|
2214
|
+
constructor(message, code, statusCode, cause,
|
|
2215
|
+
/**
|
|
2216
|
+
* Normalized Alpaca broker-rejection detail (numeric code + message + raw
|
|
2217
|
+
* body), when the underlying rejection carried one. Additive and optional:
|
|
2218
|
+
* synthetic errors and non-broker failures omit it, and every existing
|
|
2219
|
+
* consumer of `message`/`code`/`statusCode`/`cause` is unaffected.
|
|
2220
|
+
*/
|
|
2221
|
+
brokerError) {
|
|
2214
2222
|
// Rate limit (429) and server errors (5xx) are retryable
|
|
2215
2223
|
const isRetryable = statusCode === 429 || (statusCode !== undefined && statusCode >= 500);
|
|
2216
2224
|
super(message, code, "alpaca", isRetryable, cause);
|
|
2217
2225
|
this.statusCode = statusCode;
|
|
2226
|
+
this.brokerError = brokerError;
|
|
2218
2227
|
}
|
|
2219
2228
|
}
|
|
2220
2229
|
/**
|
|
@@ -2410,11 +2419,261 @@ class DuplicateClientOrderIdError extends AlpacaApiError {
|
|
|
2410
2419
|
clientOrderId,
|
|
2411
2420
|
/** Whether the colliding id was derived by the wrapper (vs caller-supplied). */
|
|
2412
2421
|
wasDerived, cause) {
|
|
2413
|
-
|
|
2422
|
+
// Carry the normalized broker payload forward from the original rejection
|
|
2423
|
+
// (the `cause`) so a consumer can read the numeric code without re-parsing.
|
|
2424
|
+
super(message, "DUPLICATE_CLIENT_ORDER_ID", 422, cause, extractAlpacaBrokerError(cause));
|
|
2414
2425
|
this.clientOrderId = clientOrderId;
|
|
2415
2426
|
this.wasDerived = wasDerived;
|
|
2416
2427
|
}
|
|
2417
2428
|
}
|
|
2429
|
+
/** Max depth walked along the `error.cause` chain when locating a broker payload. */
|
|
2430
|
+
const MAX_BROKER_ERROR_CAUSE_DEPTH = 6;
|
|
2431
|
+
/**
|
|
2432
|
+
* Narrows an unknown value to an index-signature record so nested properties
|
|
2433
|
+
* can be probed without an unsafe cast.
|
|
2434
|
+
* @param value - The value to test.
|
|
2435
|
+
* @returns true when the value is a non-null object.
|
|
2436
|
+
*/
|
|
2437
|
+
function isBrokerErrorRecord(value) {
|
|
2438
|
+
return typeof value === "object" && value !== null;
|
|
2439
|
+
}
|
|
2440
|
+
/**
|
|
2441
|
+
* Reads a finite number from an unknown value, accepting Alpaca's numeric
|
|
2442
|
+
* `code` whether it arrives as a JSON number or a numeric string.
|
|
2443
|
+
* @param value - The candidate value.
|
|
2444
|
+
* @returns The number when finite, otherwise null.
|
|
2445
|
+
*/
|
|
2446
|
+
function asBrokerCode(value) {
|
|
2447
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
2448
|
+
return value;
|
|
2449
|
+
}
|
|
2450
|
+
if (typeof value === "string" && value.trim() !== "") {
|
|
2451
|
+
const parsed = Number(value);
|
|
2452
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
2453
|
+
}
|
|
2454
|
+
return null;
|
|
2455
|
+
}
|
|
2456
|
+
/**
|
|
2457
|
+
* Reads the axios/SDK-shaped broker payload from a SINGLE node's `response`
|
|
2458
|
+
* field: an object `response.data` (`{ code, message }`) or a `response.data`
|
|
2459
|
+
* left as an unparsed JSON string (the raw-`fetch` seams attach the body as a
|
|
2460
|
+
* string). A known HTTP `response.status` is itself a broker-boundary signal —
|
|
2461
|
+
* a `422` whose body carries no numeric code is still a `422` — so a
|
|
2462
|
+
* status-only detail (`brokerCode: null`) is surfaced rather than discarded.
|
|
2463
|
+
* Returns `undefined` only when the node carries no `response` and no status.
|
|
2464
|
+
*
|
|
2465
|
+
* @param node - The candidate error-like record.
|
|
2466
|
+
* @returns The normalized detail, or undefined when the node has no response.
|
|
2467
|
+
*/
|
|
2468
|
+
function readResponseBrokerDetail(node) {
|
|
2469
|
+
const response = node.response;
|
|
2470
|
+
if (!isBrokerErrorRecord(response)) {
|
|
2471
|
+
return undefined;
|
|
2472
|
+
}
|
|
2473
|
+
const statusCode = asBrokerCode(response.status);
|
|
2474
|
+
// A known status with no structured code/message: preserve the status rather
|
|
2475
|
+
// than discarding it (a code null is never fabricated into a value).
|
|
2476
|
+
const statusOnly = statusCode === null
|
|
2477
|
+
? undefined
|
|
2478
|
+
: { brokerCode: null, brokerMessage: null, statusCode, raw: response.data };
|
|
2479
|
+
// Keep the raw body in its own const so the string narrowing survives the
|
|
2480
|
+
// JSON.parse (a reassigned `let` would widen back to `unknown` in the catch).
|
|
2481
|
+
const rawData = response.data;
|
|
2482
|
+
let parsed = rawData;
|
|
2483
|
+
if (typeof rawData === "string") {
|
|
2484
|
+
try {
|
|
2485
|
+
parsed = JSON.parse(rawData);
|
|
2486
|
+
}
|
|
2487
|
+
catch {
|
|
2488
|
+
// A non-JSON string body carries a human reason but no structured code.
|
|
2489
|
+
return { brokerCode: null, brokerMessage: rawData, statusCode, raw: rawData };
|
|
2490
|
+
}
|
|
2491
|
+
}
|
|
2492
|
+
if (!isBrokerErrorRecord(parsed)) {
|
|
2493
|
+
return statusOnly;
|
|
2494
|
+
}
|
|
2495
|
+
const brokerCode = asBrokerCode(parsed.code);
|
|
2496
|
+
const brokerMessage = typeof parsed.message === "string" ? parsed.message : null;
|
|
2497
|
+
if (brokerCode === null && brokerMessage === null) {
|
|
2498
|
+
return statusOnly;
|
|
2499
|
+
}
|
|
2500
|
+
return { brokerCode, brokerMessage, statusCode, raw: rawData };
|
|
2501
|
+
}
|
|
2502
|
+
/**
|
|
2503
|
+
* Reads the normalized broker detail from a SINGLE error-like node, without
|
|
2504
|
+
* walking its `cause` chain. Recognizes two carriers on the node: an
|
|
2505
|
+
* {@link AlpacaBrokerErrorDetail} already attached as `brokerError`, and an
|
|
2506
|
+
* axios/SDK-shaped `response` body (object or unparsed JSON string). A carrier
|
|
2507
|
+
* bearing a numeric code wins over a code-less one, so an enrichment that
|
|
2508
|
+
* resolved no code never shadows a numeric code sitting in the same node's raw
|
|
2509
|
+
* response body. Returns `undefined` when the node carries no broker payload,
|
|
2510
|
+
* so absence is never converted into a fabricated code.
|
|
2511
|
+
*
|
|
2512
|
+
* @param node - The candidate error-like value.
|
|
2513
|
+
* @returns The normalized detail, or undefined.
|
|
2514
|
+
*/
|
|
2515
|
+
function readBrokerDetailFromNode(node) {
|
|
2516
|
+
if (!isBrokerErrorRecord(node)) {
|
|
2517
|
+
return undefined;
|
|
2518
|
+
}
|
|
2519
|
+
// Carrier 1: a detail already normalized and attached by this module
|
|
2520
|
+
// (e.g. AlpacaApiError.brokerError or a value enriched via enrichAlpacaError).
|
|
2521
|
+
let attachedDetail;
|
|
2522
|
+
const attached = node.brokerError;
|
|
2523
|
+
if (isBrokerErrorRecord(attached) && "brokerCode" in attached) {
|
|
2524
|
+
attachedDetail = {
|
|
2525
|
+
brokerCode: asBrokerCode(attached.brokerCode),
|
|
2526
|
+
brokerMessage: typeof attached.brokerMessage === "string"
|
|
2527
|
+
? attached.brokerMessage
|
|
2528
|
+
: null,
|
|
2529
|
+
statusCode: asBrokerCode(attached.statusCode),
|
|
2530
|
+
raw: attached.raw,
|
|
2531
|
+
};
|
|
2532
|
+
// A numeric code on the attached detail is authoritative for this node.
|
|
2533
|
+
if (attachedDetail.brokerCode !== null) {
|
|
2534
|
+
return attachedDetail;
|
|
2535
|
+
}
|
|
2536
|
+
}
|
|
2537
|
+
// Carrier 2: an axios/SDK-shaped `response` body on the same node. Prefer a
|
|
2538
|
+
// numeric code found here over a code-less attached detail.
|
|
2539
|
+
const responseDetail = readResponseBrokerDetail(node);
|
|
2540
|
+
if (responseDetail?.brokerCode != null) {
|
|
2541
|
+
return responseDetail;
|
|
2542
|
+
}
|
|
2543
|
+
return attachedDetail ?? responseDetail;
|
|
2544
|
+
}
|
|
2545
|
+
/**
|
|
2546
|
+
* Extracts the normalized {@link AlpacaBrokerErrorDetail} from a thrown Alpaca
|
|
2547
|
+
* SDK/axios error, reading the vendor payload at `error.response.data` and,
|
|
2548
|
+
* failing that, walking the `error.cause` chain (the raw SDK error is preserved
|
|
2549
|
+
* there once a wrapper has re-thrown). Returns `undefined` when no broker
|
|
2550
|
+
* payload is present anywhere on the chain.
|
|
2551
|
+
*
|
|
2552
|
+
* Pure and outcome-independent: derived solely from Alpaca's documented error
|
|
2553
|
+
* contract, with zero reference to realized P&L, fills, or account state.
|
|
2554
|
+
*
|
|
2555
|
+
* A node bearing a numeric broker code wins immediately; a code-less detail
|
|
2556
|
+
* (status-only or message-only) found higher on the chain is held as a fallback
|
|
2557
|
+
* while the walk continues, so a numeric code sitting deeper in the `cause`
|
|
2558
|
+
* chain is never shadowed by a shallower code-less node — and when no code
|
|
2559
|
+
* exists anywhere, the code-less detail is still returned rather than discarded.
|
|
2560
|
+
*
|
|
2561
|
+
* @param error - The thrown value.
|
|
2562
|
+
* @returns The normalized broker detail, or undefined when none is present.
|
|
2563
|
+
*/
|
|
2564
|
+
function extractAlpacaBrokerError(error) {
|
|
2565
|
+
let current = error;
|
|
2566
|
+
let fallback;
|
|
2567
|
+
for (let depth = 0; depth < MAX_BROKER_ERROR_CAUSE_DEPTH && current != null; depth++) {
|
|
2568
|
+
const detail = readBrokerDetailFromNode(current);
|
|
2569
|
+
if (detail !== undefined) {
|
|
2570
|
+
if (detail.brokerCode !== null) {
|
|
2571
|
+
return detail;
|
|
2572
|
+
}
|
|
2573
|
+
if (fallback === undefined) {
|
|
2574
|
+
fallback = detail;
|
|
2575
|
+
}
|
|
2576
|
+
}
|
|
2577
|
+
if (!isBrokerErrorRecord(current)) {
|
|
2578
|
+
break;
|
|
2579
|
+
}
|
|
2580
|
+
current = current.cause;
|
|
2581
|
+
}
|
|
2582
|
+
return fallback;
|
|
2583
|
+
}
|
|
2584
|
+
/**
|
|
2585
|
+
* Returns the normalized {@link AlpacaBrokerErrorDetail} for a thrown error, or
|
|
2586
|
+
* `null` when the error carries no Alpaca broker payload. The typed
|
|
2587
|
+
* vendor-boundary replacement for reaching into `err.response.data` downstream.
|
|
2588
|
+
*
|
|
2589
|
+
* @param error - The thrown value.
|
|
2590
|
+
* @returns The normalized detail, or null.
|
|
2591
|
+
*/
|
|
2592
|
+
function getAlpacaBrokerErrorDetail(error) {
|
|
2593
|
+
return extractAlpacaBrokerError(error) ?? null;
|
|
2594
|
+
}
|
|
2595
|
+
/**
|
|
2596
|
+
* Returns Alpaca's machine-readable numeric broker error code from a thrown
|
|
2597
|
+
* error (walking the `cause` chain), or `null` when absent. The typed
|
|
2598
|
+
* replacement for `err.message.includes("42210000")`:
|
|
2599
|
+
*
|
|
2600
|
+
* ```typescript
|
|
2601
|
+
* if (getAlpacaBrokerErrorCode(err) === 42210000) { ... } // stale-order reject
|
|
2602
|
+
* ```
|
|
2603
|
+
*
|
|
2604
|
+
* The code resolves uniformly across every vendor seam: the SDK/axios path
|
|
2605
|
+
* (where `response.data` rides along for free) and the raw-`fetch` paths — the
|
|
2606
|
+
* `AlpacaTradingAPI` class `makeRequest` and the legacy order helpers, which
|
|
2607
|
+
* throw via {@link alpacaHttpError} so the verbatim status + body are carried as
|
|
2608
|
+
* a typed `.response`. A consumer branching on the stale-order `42210000` gets
|
|
2609
|
+
* the same answer regardless of which seam produced the reject, including the
|
|
2610
|
+
* dominant percent-trailing-stop tighten path where a plain `Error` previously
|
|
2611
|
+
* dropped the broker payload.
|
|
2612
|
+
*
|
|
2613
|
+
* @param error - The thrown value.
|
|
2614
|
+
* @returns The numeric broker code, or null.
|
|
2615
|
+
*/
|
|
2616
|
+
function getAlpacaBrokerErrorCode(error) {
|
|
2617
|
+
return extractAlpacaBrokerError(error)?.brokerCode ?? null;
|
|
2618
|
+
}
|
|
2619
|
+
/**
|
|
2620
|
+
* Additively enriches a thrown error with the normalized Alpaca broker detail
|
|
2621
|
+
* extracted from `source` (the original SDK/axios rejection), WITHOUT changing
|
|
2622
|
+
* the target's `message`, `name`, or prototype. It:
|
|
2623
|
+
*
|
|
2624
|
+
* - sets `target.cause = source` when the target has no cause yet, so the raw
|
|
2625
|
+
* rejection (and its `response.data`) is never lost down the wrapper chain;
|
|
2626
|
+
* - attaches the normalized {@link AlpacaBrokerErrorDetail} as
|
|
2627
|
+
* `target.brokerError` when `source` carried a broker payload.
|
|
2628
|
+
*
|
|
2629
|
+
* Purely additive by construction: a caller writes
|
|
2630
|
+
* `throw enrichAlpacaError(new Error(msg), error)` and every consumer that read
|
|
2631
|
+
* `error.message` or `error instanceof Error` before reads the identical value
|
|
2632
|
+
* after, while new consumers can call {@link getAlpacaBrokerErrorCode}. This is
|
|
2633
|
+
* the restoration for the dropped-`response.data` defect (Alpaca `42210000` /
|
|
2634
|
+
* `40310000` reaching consumers only as a lossy "status code NNN" string).
|
|
2635
|
+
*
|
|
2636
|
+
* @param target - The wrapper error about to be thrown.
|
|
2637
|
+
* @param source - The original rejection to normalize and preserve.
|
|
2638
|
+
* @returns The same `target`, typed to expose the optional `brokerError`.
|
|
2639
|
+
*/
|
|
2640
|
+
function enrichAlpacaError(target, source) {
|
|
2641
|
+
const enriched = target;
|
|
2642
|
+
if (enriched.cause === undefined && source !== undefined) {
|
|
2643
|
+
enriched.cause = source;
|
|
2644
|
+
}
|
|
2645
|
+
const detail = extractAlpacaBrokerError(source);
|
|
2646
|
+
if (detail !== undefined) {
|
|
2647
|
+
enriched.brokerError = detail;
|
|
2648
|
+
}
|
|
2649
|
+
return enriched;
|
|
2650
|
+
}
|
|
2651
|
+
/**
|
|
2652
|
+
* Builds a thrown-ready `Error` for a raw-`fetch` Alpaca rejection, carrying the
|
|
2653
|
+
* verbatim HTTP status + body as a typed `.response` so that
|
|
2654
|
+
* {@link getAlpacaBrokerErrorCode} / {@link extractAlpacaBrokerError} resolve
|
|
2655
|
+
* the numeric broker code on the `fetch` seams (the `AlpacaTradingAPI` class
|
|
2656
|
+
* `makeRequest` and the legacy functional order helpers) exactly as they
|
|
2657
|
+
* already do on the SDK seam — where the SDK/axios error carries `response.data`
|
|
2658
|
+
* for free but a hand-thrown `new Error(...)` does not.
|
|
2659
|
+
*
|
|
2660
|
+
* Purely additive by construction: the `.message` is caller-supplied and
|
|
2661
|
+
* returned byte-identical (so message string-matching consumers are
|
|
2662
|
+
* unaffected), the returned value `instanceof Error` still holds, and only the
|
|
2663
|
+
* `.response` surface is added. The `data` is the raw string body exactly as
|
|
2664
|
+
* `response.text()` returned it — {@link extractAlpacaBrokerError} parses a
|
|
2665
|
+
* JSON-string body itself, so no vendor payload is lost or reshaped here.
|
|
2666
|
+
*
|
|
2667
|
+
* @param message - The error message, thrown verbatim (never rewritten).
|
|
2668
|
+
* @param status - The HTTP status the rejection arrived on.
|
|
2669
|
+
* @param body - The raw response body (`response.text()`), preserved verbatim.
|
|
2670
|
+
* @returns An `Error` whose `.response` exposes `{ status, data: body }`.
|
|
2671
|
+
*/
|
|
2672
|
+
function alpacaHttpError(message, status, body) {
|
|
2673
|
+
return Object.assign(new Error(message), {
|
|
2674
|
+
response: { status, data: body },
|
|
2675
|
+
});
|
|
2676
|
+
}
|
|
2418
2677
|
|
|
2419
2678
|
const DEFAULT_RETRY_CONFIG = {
|
|
2420
2679
|
maxRetries: 3,
|
|
@@ -5294,7 +5553,13 @@ class AlpacaTradingAPI {
|
|
|
5294
5553
|
this.log(`Alpaca API error (${response.status}): ${errorText}`, {
|
|
5295
5554
|
type: "error",
|
|
5296
5555
|
});
|
|
5297
|
-
|
|
5556
|
+
// Additive broker-error preservation: the message is byte-identical
|
|
5557
|
+
// (existing "422"/"42210000" string-matching consumers are unaffected),
|
|
5558
|
+
// and the verbatim status + body ride along as a typed `.response` so
|
|
5559
|
+
// getAlpacaBrokerErrorCode resolves the numeric code on this fetch seam —
|
|
5560
|
+
// the dominant percent-trailing-stop tighten path and the 08-20 defect
|
|
5561
|
+
// site, where a plain Error dropped the broker's response.data.
|
|
5562
|
+
throw alpacaHttpError(`Alpaca API error (${response.status}): ${errorText}`, response.status, errorText);
|
|
5298
5563
|
}
|
|
5299
5564
|
// Handle responses with no content (e.g., 204 No Content)
|
|
5300
5565
|
if (response.status === 204 ||
|
|
@@ -5679,7 +5944,10 @@ class AlpacaTradingAPI {
|
|
|
5679
5944
|
this.log(`Order ${orderId} is not cancelable`, {
|
|
5680
5945
|
type: "error",
|
|
5681
5946
|
});
|
|
5682
|
-
|
|
5947
|
+
// Re-message stays byte-identical; the broker payload from makeRequest's
|
|
5948
|
+
// `.response` is carried onto the new error so the numeric code survives
|
|
5949
|
+
// this wrapper instead of being dropped at the re-throw.
|
|
5950
|
+
throw enrichAlpacaError(new Error(`Order ${orderId} is not cancelable`), error);
|
|
5683
5951
|
}
|
|
5684
5952
|
// Re-throw other errors
|
|
5685
5953
|
throw error;
|
|
@@ -6729,7 +6997,7 @@ async function makeRequest(auth, params) {
|
|
|
6729
6997
|
source: "AlpacaAPI",
|
|
6730
6998
|
type: "error",
|
|
6731
6999
|
});
|
|
6732
|
-
throw
|
|
7000
|
+
throw alpacaHttpError(`Alpaca API error (${response.status}): ${errorText}`, response.status, errorText);
|
|
6733
7001
|
}
|
|
6734
7002
|
catch (err) {
|
|
6735
7003
|
const error = err;
|
|
@@ -6762,7 +7030,7 @@ async function createOrder$1(auth, params) {
|
|
|
6762
7030
|
});
|
|
6763
7031
|
if (!response.ok) {
|
|
6764
7032
|
const errorText = await response.text();
|
|
6765
|
-
throw
|
|
7033
|
+
throw alpacaHttpError(`Failed to create order: ${response.status} ${response.statusText} ${errorText}`, response.status, errorText);
|
|
6766
7034
|
}
|
|
6767
7035
|
return (await response.json());
|
|
6768
7036
|
}
|
|
@@ -6809,7 +7077,7 @@ async function getOrders$1(auth, params = {}) {
|
|
|
6809
7077
|
});
|
|
6810
7078
|
if (!response.ok) {
|
|
6811
7079
|
const errorText = await response.text();
|
|
6812
|
-
throw
|
|
7080
|
+
throw alpacaHttpError(`Failed to get orders: ${response.status} ${response.statusText} ${errorText}`, response.status, errorText);
|
|
6813
7081
|
}
|
|
6814
7082
|
const orders = (await response.json());
|
|
6815
7083
|
allOrders.push(...orders);
|
|
@@ -6870,7 +7138,7 @@ async function cancelAllOrders$1(auth) {
|
|
|
6870
7138
|
});
|
|
6871
7139
|
if (!response.ok) {
|
|
6872
7140
|
const errorText = await response.text();
|
|
6873
|
-
throw
|
|
7141
|
+
throw alpacaHttpError(`Failed to cancel orders: ${response.status} ${response.statusText} ${errorText}`, response.status, errorText);
|
|
6874
7142
|
}
|
|
6875
7143
|
return (await response.json());
|
|
6876
7144
|
}
|
|
@@ -6903,7 +7171,7 @@ async function getOrder$1(auth, orderId, nested) {
|
|
|
6903
7171
|
});
|
|
6904
7172
|
if (!response.ok) {
|
|
6905
7173
|
const errorText = await response.text();
|
|
6906
|
-
throw
|
|
7174
|
+
throw alpacaHttpError(`Failed to get order: ${response.status} ${response.statusText} ${errorText}`, response.status, errorText);
|
|
6907
7175
|
}
|
|
6908
7176
|
return (await response.json());
|
|
6909
7177
|
}
|
|
@@ -6936,7 +7204,7 @@ async function replaceOrder$1(auth, orderId, params) {
|
|
|
6936
7204
|
});
|
|
6937
7205
|
if (!response.ok) {
|
|
6938
7206
|
const errorText = await response.text();
|
|
6939
|
-
throw
|
|
7207
|
+
throw alpacaHttpError(`Failed to replace order: ${response.status} ${response.statusText} ${errorText}`, response.status, errorText);
|
|
6940
7208
|
}
|
|
6941
7209
|
return (await response.json());
|
|
6942
7210
|
}
|
|
@@ -6969,7 +7237,7 @@ async function cancelOrder$1(auth, orderId) {
|
|
|
6969
7237
|
return { success: false, message: `Order not found: ${orderId}` };
|
|
6970
7238
|
}
|
|
6971
7239
|
else {
|
|
6972
|
-
throw
|
|
7240
|
+
throw alpacaHttpError(`Failed to cancel order: ${response.status} ${response.statusText} ${errorText}`, response.status, errorText);
|
|
6973
7241
|
}
|
|
6974
7242
|
}
|
|
6975
7243
|
return { success: true };
|
|
@@ -12860,6 +13128,66 @@ var strategyNs = /*#__PURE__*/Object.freeze({
|
|
|
12860
13128
|
calculateRollingSortino: calculateRollingSortino
|
|
12861
13129
|
});
|
|
12862
13130
|
|
|
13131
|
+
/**
|
|
13132
|
+
* Round a PRICE-scale indicator output to a precision derived from its own
|
|
13133
|
+
* magnitude, rather than a hardcoded 2 decimal places.
|
|
13134
|
+
*
|
|
13135
|
+
* A flat `toFixed(2)` silently destroys every sub-penny price — a $0.0003
|
|
13136
|
+
* microcap's bands collapse to `0.00`, and a MACD histogram of a low-priced
|
|
13137
|
+
* name rounds to nothing (F7.2). Precision must scale with the price: values at
|
|
13138
|
+
* or above $1 keep the conventional 2dp, while sub-dollar values keep ~4
|
|
13139
|
+
* significant figures so the number survives its own scale. Non-finite inputs
|
|
13140
|
+
* pass through untouched — totality of the underlying value is the caller's
|
|
13141
|
+
* responsibility, this helper only quantises.
|
|
13142
|
+
*
|
|
13143
|
+
* The `>= $1` branch delegates to `toFixed(2)` rather than re-deriving it as
|
|
13144
|
+
* `Math.round(value * 100) / 100`. The two disagree wherever the intermediate
|
|
13145
|
+
* `value * 100` rounds onto an exact `.5` that the decimal value sits just
|
|
13146
|
+
* below (`1.045` → `1.05` vs `1.04`), which would make this helper shift
|
|
13147
|
+
* ordinary dollar prices by a cent — a behaviour change well outside repairing
|
|
13148
|
+
* sub-penny collapse. Delegating keeps the common case byte-identical to the
|
|
13149
|
+
* historical output by construction, which matters because the same function
|
|
13150
|
+
* computes indicators for unit tests, backtests, paper and live.
|
|
13151
|
+
*
|
|
13152
|
+
* @param value - A price-scale indicator output (band, EMA, MACD component).
|
|
13153
|
+
* @returns The value rounded to a scale-appropriate precision.
|
|
13154
|
+
*/
|
|
13155
|
+
function roundToPriceScale(value) {
|
|
13156
|
+
if (!Number.isFinite(value))
|
|
13157
|
+
return value;
|
|
13158
|
+
const abs = Math.abs(value);
|
|
13159
|
+
if (abs === 0)
|
|
13160
|
+
return 0;
|
|
13161
|
+
if (abs >= 1)
|
|
13162
|
+
return parseFloat(value.toFixed(2));
|
|
13163
|
+
// Sub-dollar: decimals = leading zeros after the point + 4 significant figures,
|
|
13164
|
+
// capped so the factor stays within safe-integer range.
|
|
13165
|
+
const decimals = Math.min(12, Math.ceil(-Math.log10(abs)) + 4);
|
|
13166
|
+
const factor = 10 ** decimals;
|
|
13167
|
+
return Math.round(value * factor) / factor;
|
|
13168
|
+
}
|
|
13169
|
+
/**
|
|
13170
|
+
* Relative Strength Index from average gain / average loss, total on the
|
|
13171
|
+
* degenerate flat window.
|
|
13172
|
+
*
|
|
13173
|
+
* When a window has no losses the Wilder ratio `avgGain / avgLoss` is
|
|
13174
|
+
* `+Infinity` (→ RSI 100); on a perfectly flat window it is `0 / 0 = NaN`,
|
|
13175
|
+
* which the naive formula propagates straight into the output. A flat window
|
|
13176
|
+
* carries no momentum, so its RSI is the neutral 50 — never NaN. This mirrors
|
|
13177
|
+
* the engine's live RSI guards (a constant series scores neutral, an all-gains
|
|
13178
|
+
* series scores 100).
|
|
13179
|
+
*
|
|
13180
|
+
* @param avgGain - Average gain over the period (>= 0).
|
|
13181
|
+
* @param avgLoss - Average loss over the period (>= 0).
|
|
13182
|
+
* @returns RSI in [0, 100]; 50 for a flat window, 100 for an all-gains window.
|
|
13183
|
+
*/
|
|
13184
|
+
function rsiFromAverages(avgGain, avgLoss) {
|
|
13185
|
+
if (avgLoss === 0)
|
|
13186
|
+
return avgGain === 0 ? 50 : 100;
|
|
13187
|
+
const rs = avgGain / avgLoss;
|
|
13188
|
+
const rsi = 100 - 100 / (1 + rs);
|
|
13189
|
+
return Number.isFinite(rsi) ? rsi : 50;
|
|
13190
|
+
}
|
|
12863
13191
|
/**
|
|
12864
13192
|
* Calculates Bollinger Bands for a given set of price data.
|
|
12865
13193
|
* Bollinger Bands consist of a middle band (SMA) and two outer bands
|
|
@@ -12892,9 +13220,9 @@ function calculateBollingerBands(priceData, { period = 20, standardDeviations =
|
|
|
12892
13220
|
const lowerBand = sma - standardDeviation * standardDeviations;
|
|
12893
13221
|
result.push({
|
|
12894
13222
|
date: priceData[i].date,
|
|
12895
|
-
middle:
|
|
12896
|
-
upper:
|
|
12897
|
-
lower:
|
|
13223
|
+
middle: roundToPriceScale(sma),
|
|
13224
|
+
upper: roundToPriceScale(upperBand),
|
|
13225
|
+
lower: roundToPriceScale(lowerBand),
|
|
12898
13226
|
close: priceData[i].close,
|
|
12899
13227
|
});
|
|
12900
13228
|
}
|
|
@@ -12936,11 +13264,11 @@ function calculateEMA(priceData, { period = 20, period2 = 9 } = {}) {
|
|
|
12936
13264
|
// Add first EMA(s)
|
|
12937
13265
|
const firstEntry = {
|
|
12938
13266
|
date: priceData[Math.max(period, period2 || 0) - 1].date,
|
|
12939
|
-
ema:
|
|
13267
|
+
ema: roundToPriceScale(prevEMA),
|
|
12940
13268
|
close: priceData[Math.max(period, period2 || 0) - 1].close,
|
|
12941
13269
|
};
|
|
12942
13270
|
if (period2) {
|
|
12943
|
-
firstEntry.ema2 =
|
|
13271
|
+
firstEntry.ema2 = roundToPriceScale(prevEMA2);
|
|
12944
13272
|
}
|
|
12945
13273
|
result.push(firstEntry);
|
|
12946
13274
|
// Calculate EMA for remaining periods
|
|
@@ -12950,13 +13278,13 @@ function calculateEMA(priceData, { period = 20, period2 = 9 } = {}) {
|
|
|
12950
13278
|
prevEMA = currentEMA;
|
|
12951
13279
|
const entry = {
|
|
12952
13280
|
date: priceData[i].date,
|
|
12953
|
-
ema:
|
|
13281
|
+
ema: roundToPriceScale(currentEMA),
|
|
12954
13282
|
close: currentClose,
|
|
12955
13283
|
};
|
|
12956
13284
|
if (period2) {
|
|
12957
13285
|
const currentEMA2 = (currentClose - prevEMA2) * multiplier2 + prevEMA2;
|
|
12958
13286
|
prevEMA2 = currentEMA2;
|
|
12959
|
-
entry.ema2 =
|
|
13287
|
+
entry.ema2 = roundToPriceScale(currentEMA2);
|
|
12960
13288
|
}
|
|
12961
13289
|
result.push(entry);
|
|
12962
13290
|
}
|
|
@@ -13034,7 +13362,7 @@ function calculateFibonacciLevels(priceData, { lookbackPeriod = 20, retracementL
|
|
|
13034
13362
|
: swingHigh - priceRange * level;
|
|
13035
13363
|
levels.push({
|
|
13036
13364
|
level,
|
|
13037
|
-
price:
|
|
13365
|
+
price: roundToPriceScale(price),
|
|
13038
13366
|
type: "retracement",
|
|
13039
13367
|
});
|
|
13040
13368
|
});
|
|
@@ -13048,7 +13376,7 @@ function calculateFibonacciLevels(priceData, { lookbackPeriod = 20, retracementL
|
|
|
13048
13376
|
: swingHigh + priceRange * (level - 1); // For uptrend
|
|
13049
13377
|
levels.push({
|
|
13050
13378
|
level,
|
|
13051
|
-
price:
|
|
13379
|
+
price: roundToPriceScale(price),
|
|
13052
13380
|
type: "extension",
|
|
13053
13381
|
});
|
|
13054
13382
|
});
|
|
@@ -13111,9 +13439,9 @@ function calculateMACD(priceData, { shortPeriod = 12, longPeriod = 26, signalPer
|
|
|
13111
13439
|
const hist = macdValue - signalEMA;
|
|
13112
13440
|
result.push({
|
|
13113
13441
|
date: emaLong[i].date, // Use emaLong's date for alignment
|
|
13114
|
-
macd:
|
|
13115
|
-
signal:
|
|
13116
|
-
histogram:
|
|
13442
|
+
macd: roundToPriceScale(macdValue),
|
|
13443
|
+
signal: roundToPriceScale(signalEMA),
|
|
13444
|
+
histogram: roundToPriceScale(hist),
|
|
13117
13445
|
close: emaLong[i].close,
|
|
13118
13446
|
});
|
|
13119
13447
|
}
|
|
@@ -13148,9 +13476,9 @@ function calculateRSI(priceData, { period = 14 } = {}) {
|
|
|
13148
13476
|
}
|
|
13149
13477
|
avgGain = avgGain / period;
|
|
13150
13478
|
avgLoss = avgLoss / period;
|
|
13151
|
-
// Calculate RSI for the first period
|
|
13152
|
-
|
|
13153
|
-
let rsi =
|
|
13479
|
+
// Calculate RSI for the first period (total on a flat window — see
|
|
13480
|
+
// rsiFromAverages: a constant series scores the neutral 50, never NaN).
|
|
13481
|
+
let rsi = rsiFromAverages(avgGain, avgLoss);
|
|
13154
13482
|
result.push({
|
|
13155
13483
|
date: priceData[period].date,
|
|
13156
13484
|
rsi: parseFloat(rsi.toFixed(2)),
|
|
@@ -13164,8 +13492,7 @@ function calculateRSI(priceData, { period = 14 } = {}) {
|
|
|
13164
13492
|
// Use smoothed averages
|
|
13165
13493
|
avgGain = (avgGain * (period - 1) + gain) / period;
|
|
13166
13494
|
avgLoss = (avgLoss * (period - 1) + loss) / period;
|
|
13167
|
-
|
|
13168
|
-
rsi = 100 - 100 / (1 + rs);
|
|
13495
|
+
rsi = rsiFromAverages(avgGain, avgLoss);
|
|
13169
13496
|
result.push({
|
|
13170
13497
|
date: priceData[i].date,
|
|
13171
13498
|
rsi: parseFloat(rsi.toFixed(2)),
|
|
@@ -13186,6 +13513,20 @@ function calculateRSI(priceData, { period = 14 } = {}) {
|
|
|
13186
13513
|
* @returns An array of StochData objects containing the calculated %K and %D values.
|
|
13187
13514
|
*/
|
|
13188
13515
|
function calculateStochasticOscillator(priceData, { lookbackPeriod = 5, signalPeriod = 3, smoothingFactor = 3, } = {}) {
|
|
13516
|
+
// Each period is a divisor (`kSum / min(len, smoothingFactor)`) and a slice
|
|
13517
|
+
// width. A zero or fractional period therefore divides by zero or slices an
|
|
13518
|
+
// empty window, producing NaN/Infinity %K and %D — an oscillator reading that
|
|
13519
|
+
// is never true and never false. The periods are caller-supplied constants
|
|
13520
|
+
// rather than market data, so an invalid one is a programming error and is
|
|
13521
|
+
// reported as such, matching the ATR and volatility primitives.
|
|
13522
|
+
if (!Number.isInteger(lookbackPeriod) ||
|
|
13523
|
+
lookbackPeriod < 1 ||
|
|
13524
|
+
!Number.isInteger(signalPeriod) ||
|
|
13525
|
+
signalPeriod < 1 ||
|
|
13526
|
+
!Number.isInteger(smoothingFactor) ||
|
|
13527
|
+
smoothingFactor < 1) {
|
|
13528
|
+
throw new Error("calculateStochasticOscillator: lookbackPeriod, signalPeriod and smoothingFactor must be positive integers");
|
|
13529
|
+
}
|
|
13189
13530
|
if (priceData.length < lookbackPeriod) {
|
|
13190
13531
|
logIfDebug(`Insufficient data for Stochastic Oscillator calculation: required periods: ${lookbackPeriod}, but only received ${priceData.length} periods of data`);
|
|
13191
13532
|
return [];
|
|
@@ -13226,6 +13567,48 @@ function calculateStochasticOscillator(priceData, { lookbackPeriod = 5, signalPe
|
|
|
13226
13567
|
}
|
|
13227
13568
|
return result;
|
|
13228
13569
|
}
|
|
13570
|
+
/**
|
|
13571
|
+
* Collapses a cluster of nearby pivots into one volume-weighted level, or
|
|
13572
|
+
* reports that the cluster evidences no level at all.
|
|
13573
|
+
*
|
|
13574
|
+
* Both outputs are volume-weighted: the price is the volume-weighted mean of
|
|
13575
|
+
* the cluster's pivots, and the strength is the pivot count weighted by each
|
|
13576
|
+
* pivot's share of cluster volume. That weighting is undefined when the cluster
|
|
13577
|
+
* transacted no volume — `0 / 0` makes both NaN. A NaN level is strictly worse
|
|
13578
|
+
* than no level: every comparison against NaN is false, so a stop or target
|
|
13579
|
+
* placed off one is silently never triggered, leaving the position unprotected
|
|
13580
|
+
* while appearing protected.
|
|
13581
|
+
*
|
|
13582
|
+
* Zero cluster volume is a real market state rather than corrupt input — halted,
|
|
13583
|
+
* pre-market-thin and synthetic warm-up bars all report it. A support or
|
|
13584
|
+
* resistance level means price transacted enough there to turn the market, so a
|
|
13585
|
+
* cluster with no volume has not evidenced one. `SupportResistanceLevel` types
|
|
13586
|
+
* both fields as non-optional numbers, which leaves omitting the level as the
|
|
13587
|
+
* only honest way to say so.
|
|
13588
|
+
*
|
|
13589
|
+
* @param cluster - The nearby pivots to collapse into a single level.
|
|
13590
|
+
* @param currentPrice - The bar's close, which classifies the level's side.
|
|
13591
|
+
* @returns The aggregated level, or null when the cluster evidences none.
|
|
13592
|
+
*/
|
|
13593
|
+
function aggregatePivotCluster(cluster, currentPrice) {
|
|
13594
|
+
const totalVolume = cluster.reduce((sum, p) => sum + p.volume, 0);
|
|
13595
|
+
// Negated `> 0` so NaN and negative totals are rejected alongside zero: no
|
|
13596
|
+
// volume weighting survives any of them.
|
|
13597
|
+
if (!(totalVolume > 0))
|
|
13598
|
+
return null;
|
|
13599
|
+
const avgPrice = cluster.reduce((sum, p) => sum + p.price * p.volume, 0) / totalVolume;
|
|
13600
|
+
const strength = cluster.reduce((sum, p) => sum + p.count * (p.volume / totalVolume), 0);
|
|
13601
|
+
if (!Number.isFinite(avgPrice) || !Number.isFinite(strength))
|
|
13602
|
+
return null;
|
|
13603
|
+
return {
|
|
13604
|
+
// The level is a price, so its precision follows the price's magnitude
|
|
13605
|
+
// (F7.2). Strength is a count-weighted score rather than a price and keeps
|
|
13606
|
+
// the conventional 2dp.
|
|
13607
|
+
price: roundToPriceScale(avgPrice),
|
|
13608
|
+
strength: parseFloat(strength.toFixed(2)),
|
|
13609
|
+
type: avgPrice > currentPrice ? "resistance" : "support",
|
|
13610
|
+
};
|
|
13611
|
+
}
|
|
13229
13612
|
/**
|
|
13230
13613
|
* Calculates support and resistance levels based on price data.
|
|
13231
13614
|
* Support and resistance levels are price levels at which a stock tends to stop and reverse.
|
|
@@ -13246,9 +13629,22 @@ function calculateSupportAndResistance(priceData, { maxLevels = 5, lookbackPerio
|
|
|
13246
13629
|
const priceChanges = analysisWindow
|
|
13247
13630
|
.slice(1)
|
|
13248
13631
|
.map((bar, idx) => Math.abs(bar.close - analysisWindow[idx].close));
|
|
13249
|
-
|
|
13250
|
-
|
|
13251
|
-
|
|
13632
|
+
// A single-bar window produces no price changes to average, and a
|
|
13633
|
+
// non-positive reference close cannot scale one — `0 / 0` and `x / 0` make
|
|
13634
|
+
// the relative volatility NaN or Infinity. Volatility is the sole input to
|
|
13635
|
+
// both the pivot sensitivity and the level-grouping gap below, so a
|
|
13636
|
+
// non-finite value silently disables every comparison that depends on it
|
|
13637
|
+
// (each is false against NaN). Unmeasurable volatility resolves to zero,
|
|
13638
|
+
// under which each pivot stands as its own level instead of being merged on
|
|
13639
|
+
// a meaningless ratio.
|
|
13640
|
+
const referenceClose = analysisWindow[0].close;
|
|
13641
|
+
const avgPriceChange = priceChanges.length > 0
|
|
13642
|
+
? priceChanges.reduce((sum, change) => sum + change, 0) /
|
|
13643
|
+
priceChanges.length
|
|
13644
|
+
: 0;
|
|
13645
|
+
const volatility = referenceClose > 0 && Number.isFinite(avgPriceChange)
|
|
13646
|
+
? avgPriceChange / referenceClose
|
|
13647
|
+
: 0; // Relative volatility
|
|
13252
13648
|
// **Adjust Sensitivity and minGapBetweenLevels Dynamically**
|
|
13253
13649
|
const sensitivity = volatility * 2; // Adjust the multiplier as needed
|
|
13254
13650
|
const minGapBetweenLevels = volatility * 100; // Convert to percentage
|
|
@@ -13257,8 +13653,16 @@ function calculateSupportAndResistance(priceData, { maxLevels = 5, lookbackPerio
|
|
|
13257
13653
|
const curr = analysisWindow[j];
|
|
13258
13654
|
const prevBar = analysisWindow[j - 1];
|
|
13259
13655
|
const nextBar = analysisWindow[j + 1];
|
|
13656
|
+
// A pivot is matched against existing candidates by a *relative* gap
|
|
13657
|
+
// measured against its own price, so a non-positive reference price makes
|
|
13658
|
+
// that ratio meaningless: zero divides to NaN or Infinity (which never
|
|
13659
|
+
// compares below the sensitivity, so the pivot never merges), and a
|
|
13660
|
+
// negative price inverts the comparison (so everything merges). A bar
|
|
13661
|
+
// without a positive high or low carries no tradeable level either way.
|
|
13260
13662
|
// Check for high pivot
|
|
13261
|
-
if (curr.high >
|
|
13663
|
+
if (curr.high > 0 &&
|
|
13664
|
+
curr.high > prevBar.high &&
|
|
13665
|
+
curr.high > nextBar.high) {
|
|
13262
13666
|
const existingPivot = pivotPoints.find((p) => Math.abs(p.price - curr.high) / curr.high < sensitivity);
|
|
13263
13667
|
if (existingPivot) {
|
|
13264
13668
|
existingPivot.count++;
|
|
@@ -13269,7 +13673,7 @@ function calculateSupportAndResistance(priceData, { maxLevels = 5, lookbackPerio
|
|
|
13269
13673
|
}
|
|
13270
13674
|
}
|
|
13271
13675
|
// Check for low pivot
|
|
13272
|
-
if (curr.low < prevBar.low && curr.low < nextBar.low) {
|
|
13676
|
+
if (curr.low > 0 && curr.low < prevBar.low && curr.low < nextBar.low) {
|
|
13273
13677
|
const existingPivot = pivotPoints.find((p) => Math.abs(p.price - curr.low) / curr.low < sensitivity);
|
|
13274
13678
|
if (existingPivot) {
|
|
13275
13679
|
existingPivot.count++;
|
|
@@ -13299,33 +13703,17 @@ function calculateSupportAndResistance(priceData, { maxLevels = 5, lookbackPerio
|
|
|
13299
13703
|
}
|
|
13300
13704
|
else {
|
|
13301
13705
|
// Process current group
|
|
13302
|
-
|
|
13303
|
-
|
|
13304
|
-
|
|
13305
|
-
totalVolume;
|
|
13306
|
-
const totalStrength = currentGroup.reduce((sum, p) => sum + p.count * (p.volume / totalVolume), 0);
|
|
13307
|
-
levels.push({
|
|
13308
|
-
price: parseFloat(avgPrice.toFixed(2)),
|
|
13309
|
-
strength: parseFloat(totalStrength.toFixed(2)),
|
|
13310
|
-
type: avgPrice > currentPrice ? "resistance" : "support",
|
|
13311
|
-
});
|
|
13312
|
-
}
|
|
13706
|
+
const level = aggregatePivotCluster(currentGroup, currentPrice);
|
|
13707
|
+
if (level)
|
|
13708
|
+
levels.push(level);
|
|
13313
13709
|
currentGroup = [pivotPoints[j]];
|
|
13314
13710
|
}
|
|
13315
13711
|
}
|
|
13316
13712
|
}
|
|
13317
13713
|
// Process final group
|
|
13318
|
-
|
|
13319
|
-
|
|
13320
|
-
|
|
13321
|
-
totalVolume;
|
|
13322
|
-
const totalStrength = currentGroup.reduce((sum, p) => sum + p.count * (p.volume / totalVolume), 0);
|
|
13323
|
-
levels.push({
|
|
13324
|
-
price: parseFloat(avgPrice.toFixed(2)),
|
|
13325
|
-
strength: parseFloat(totalStrength.toFixed(2)),
|
|
13326
|
-
type: avgPrice > currentPrice ? "resistance" : "support",
|
|
13327
|
-
});
|
|
13328
|
-
}
|
|
13714
|
+
const finalGroupLevel = aggregatePivotCluster(currentGroup, currentPrice);
|
|
13715
|
+
if (finalGroupLevel)
|
|
13716
|
+
levels.push(finalGroupLevel);
|
|
13329
13717
|
// Sort by strength and limit
|
|
13330
13718
|
const finalLevels = levels
|
|
13331
13719
|
.sort((a, b) => b.strength - a.strength)
|
|
@@ -53772,7 +54160,7 @@ async function createTrailingStop(client, params) {
|
|
|
53772
54160
|
log$g(`Trailing stop creation failed for ${params.symbol}: ${err.message}`, {
|
|
53773
54161
|
type: "error",
|
|
53774
54162
|
});
|
|
53775
|
-
throw new Error(`Failed to create trailing stop for ${params.symbol}: ${err.message}`);
|
|
54163
|
+
throw enrichAlpacaError(new Error(`Failed to create trailing stop for ${params.symbol}: ${err.message}`), error);
|
|
53776
54164
|
}
|
|
53777
54165
|
}
|
|
53778
54166
|
/**
|
|
@@ -53838,7 +54226,11 @@ async function updateTrailingStop(client, orderId, updates) {
|
|
|
53838
54226
|
log$g(`Trailing stop update failed for ${orderId}: ${err.message}`, {
|
|
53839
54227
|
type: "error",
|
|
53840
54228
|
});
|
|
53841
|
-
|
|
54229
|
+
// Preserve Alpaca's `response.data` (numeric code `42210000` etc.) that the
|
|
54230
|
+
// SDK reduces to a bare "status code NNN" message. This is THE trailing-stop
|
|
54231
|
+
// modify path; dropping the code here left the consumer unable to tell a
|
|
54232
|
+
// stale-order reject from a benign race, blind-failing the profit lock.
|
|
54233
|
+
throw enrichAlpacaError(new Error(`Failed to update trailing stop ${orderId}: ${err.message}`), error);
|
|
53842
54234
|
}
|
|
53843
54235
|
}
|
|
53844
54236
|
/**
|
|
@@ -53879,7 +54271,7 @@ async function getTrailingStopHWM(client, orderId) {
|
|
|
53879
54271
|
log$g(`Failed to get trailing stop HWM for ${orderId}: ${err.message}`, {
|
|
53880
54272
|
type: "error",
|
|
53881
54273
|
});
|
|
53882
|
-
throw new Error(`Failed to get trailing stop HWM for ${orderId}: ${err.message}`);
|
|
54274
|
+
throw enrichAlpacaError(new Error(`Failed to get trailing stop HWM for ${orderId}: ${err.message}`), error);
|
|
53883
54275
|
}
|
|
53884
54276
|
}
|
|
53885
54277
|
/**
|
|
@@ -53908,12 +54300,12 @@ async function cancelTrailingStop(client, orderId) {
|
|
|
53908
54300
|
log$g(`Trailing stop ${orderId} is not cancelable (may already be filled or canceled)`, {
|
|
53909
54301
|
type: "warn",
|
|
53910
54302
|
});
|
|
53911
|
-
throw new Error(`Trailing stop ${orderId} is not cancelable: order may already be filled or canceled`);
|
|
54303
|
+
throw enrichAlpacaError(new Error(`Trailing stop ${orderId} is not cancelable: order may already be filled or canceled`), error);
|
|
53912
54304
|
}
|
|
53913
54305
|
log$g(`Failed to cancel trailing stop ${orderId}: ${err.message}`, {
|
|
53914
54306
|
type: "error",
|
|
53915
54307
|
});
|
|
53916
|
-
throw new Error(`Failed to cancel trailing stop ${orderId}: ${err.message}`);
|
|
54308
|
+
throw enrichAlpacaError(new Error(`Failed to cancel trailing stop ${orderId}: ${err.message}`), error);
|
|
53917
54309
|
}
|
|
53918
54310
|
}
|
|
53919
54311
|
/**
|
|
@@ -53997,9 +54389,14 @@ async function createPortfolioTrailingStops(client, params) {
|
|
|
53997
54389
|
}
|
|
53998
54390
|
catch (err) {
|
|
53999
54391
|
const errorMessage = err.message;
|
|
54000
|
-
|
|
54392
|
+
// Preserve the broker's numeric code (e.g. 42210000) rather than
|
|
54393
|
+
// reducing the swallowed per-item failure to its flattened message —
|
|
54394
|
+
// this loop only logs failures, so the log is the preservation target.
|
|
54395
|
+
const brokerCode = getAlpacaBrokerErrorCode(err);
|
|
54396
|
+
errors.push({ symbol, error: errorMessage, brokerCode });
|
|
54001
54397
|
log$g(`Failed to create trailing stop for ${symbol}: ${errorMessage}`, {
|
|
54002
54398
|
type: "error",
|
|
54399
|
+
metadata: { brokerCode },
|
|
54003
54400
|
});
|
|
54004
54401
|
}
|
|
54005
54402
|
}
|
|
@@ -54009,7 +54406,9 @@ async function createPortfolioTrailingStops(client, params) {
|
|
|
54009
54406
|
const skippedCount = positions.length - successCount - failureCount;
|
|
54010
54407
|
log$g(`Portfolio trailing stops complete: ${successCount} created, ${failureCount} failed, ${skippedCount} skipped`, { type: "info" });
|
|
54011
54408
|
if (errors.length > 0) {
|
|
54012
|
-
log$g(`Failed symbols: ${errors
|
|
54409
|
+
log$g(`Failed symbols: ${errors
|
|
54410
|
+
.map((e) => `${e.symbol} (${e.error}${e.brokerCode !== null ? `, code ${e.brokerCode}` : ""})`)
|
|
54411
|
+
.join(", ")}`, {
|
|
54013
54412
|
type: "warn",
|
|
54014
54413
|
});
|
|
54015
54414
|
}
|
|
@@ -54020,7 +54419,7 @@ async function createPortfolioTrailingStops(client, params) {
|
|
|
54020
54419
|
log$g(`Failed to create portfolio trailing stops: ${err.message}`, {
|
|
54021
54420
|
type: "error",
|
|
54022
54421
|
});
|
|
54023
|
-
throw new Error(`Failed to create portfolio trailing stops: ${err.message}`);
|
|
54422
|
+
throw enrichAlpacaError(new Error(`Failed to create portfolio trailing stops: ${err.message}`), error);
|
|
54024
54423
|
}
|
|
54025
54424
|
}
|
|
54026
54425
|
/**
|
|
@@ -54059,7 +54458,7 @@ async function getOpenTrailingStops(client, symbol) {
|
|
|
54059
54458
|
catch (error) {
|
|
54060
54459
|
const err = error;
|
|
54061
54460
|
log$g(`Failed to get open trailing stops: ${err.message}`, { type: "error" });
|
|
54062
|
-
throw new Error(`Failed to get open trailing stops: ${err.message}`);
|
|
54461
|
+
throw enrichAlpacaError(new Error(`Failed to get open trailing stops: ${err.message}`), error);
|
|
54063
54462
|
}
|
|
54064
54463
|
}
|
|
54065
54464
|
/**
|
|
@@ -54107,7 +54506,10 @@ async function cancelTrailingStopsForSymbol(client, symbol) {
|
|
|
54107
54506
|
canceledCount++;
|
|
54108
54507
|
}
|
|
54109
54508
|
catch (err) {
|
|
54110
|
-
|
|
54509
|
+
// Keep the broker's numeric code alongside the message so the swallowed
|
|
54510
|
+
// per-item cancel failure stays diagnosable in the summary log.
|
|
54511
|
+
const brokerCode = getAlpacaBrokerErrorCode(err);
|
|
54512
|
+
errors.push(`${order.id}: ${err.message}${brokerCode !== null ? ` (code ${brokerCode})` : ""}`);
|
|
54111
54513
|
}
|
|
54112
54514
|
}
|
|
54113
54515
|
if (errors.length > 0) {
|
|
@@ -58344,7 +58746,12 @@ async function resolveDuplicateSubmission(client, clientOrderId, symbol, cause)
|
|
|
58344
58746
|
catch (lookupError) {
|
|
58345
58747
|
const reason = lookupError instanceof Error ? lookupError.message : String(lookupError);
|
|
58346
58748
|
log$6(`Duplicate-order lookup failed for ${clientOrderId}; failing closed (no resubmit): ${reason}`, { type: "error", symbol, metadata: { clientOrderId } });
|
|
58347
|
-
|
|
58749
|
+
// The typed error represents the ORIGINAL duplicate rejection, so its broker
|
|
58750
|
+
// payload must come from `cause` (the 422), not from the lookup failure.
|
|
58751
|
+
// Chain the lookup error ahead of the original 422 (and carry the 422's
|
|
58752
|
+
// normalized detail onto it) so both are diagnosable and
|
|
58753
|
+
// getAlpacaBrokerErrorCode still resolves the duplicate code.
|
|
58754
|
+
throw new DuplicateClientOrderIdError(`Duplicate client_order_id "${clientOrderId}" rejected by Alpaca and the existing-order lookup failed; refusing to resubmit (possible live duplicate)`, clientOrderId, false, enrichAlpacaError(lookupError instanceof Error ? lookupError : new Error(reason), cause));
|
|
58348
58755
|
}
|
|
58349
58756
|
if (existing && !TERMINAL_DEAD_ORDER_STATUSES.has(existing.status)) {
|
|
58350
58757
|
log$6(`client_order_id ${clientOrderId} already submitted (status=${existing.status}); returning existing order ${existing.id} as idempotent success`, {
|
|
@@ -58478,7 +58885,7 @@ async function createOrder(client, params) {
|
|
|
58478
58885
|
symbol,
|
|
58479
58886
|
metadata: { params: submission },
|
|
58480
58887
|
});
|
|
58481
|
-
throw new Error(`Failed to create ${type} order for ${symbol}: ${errorMessage}`);
|
|
58888
|
+
throw enrichAlpacaError(new Error(`Failed to create ${type} order for ${symbol}: ${errorMessage}`), error);
|
|
58482
58889
|
}
|
|
58483
58890
|
}
|
|
58484
58891
|
/**
|
|
@@ -58507,7 +58914,7 @@ async function getOrder(client, orderId) {
|
|
|
58507
58914
|
catch (error) {
|
|
58508
58915
|
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
58509
58916
|
log$6(`Failed to fetch order ${orderId}: ${errorMessage}`, { type: "error" });
|
|
58510
|
-
throw new Error(`Failed to fetch order ${orderId}: ${errorMessage}`);
|
|
58917
|
+
throw enrichAlpacaError(new Error(`Failed to fetch order ${orderId}: ${errorMessage}`), error);
|
|
58511
58918
|
}
|
|
58512
58919
|
}
|
|
58513
58920
|
/**
|
|
@@ -58570,7 +58977,7 @@ async function getOrders(client, params = {}) {
|
|
|
58570
58977
|
catch (error) {
|
|
58571
58978
|
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
58572
58979
|
log$6(`Failed to fetch orders: ${errorMessage}`, { type: "error" });
|
|
58573
|
-
throw new Error(`Failed to fetch orders: ${errorMessage}`);
|
|
58980
|
+
throw enrichAlpacaError(new Error(`Failed to fetch orders: ${errorMessage}`), error);
|
|
58574
58981
|
}
|
|
58575
58982
|
}
|
|
58576
58983
|
/**
|
|
@@ -58600,16 +59007,16 @@ async function cancelOrder(client, orderId) {
|
|
|
58600
59007
|
log$6(`Order ${orderId} is not cancelable (may already be filled or canceled)`, {
|
|
58601
59008
|
type: "warn",
|
|
58602
59009
|
});
|
|
58603
|
-
throw new Error(`Order ${orderId} is not cancelable`);
|
|
59010
|
+
throw enrichAlpacaError(new Error(`Order ${orderId} is not cancelable`), error);
|
|
58604
59011
|
}
|
|
58605
59012
|
if (errorMessage.includes("404") || errorMessage.includes("not found")) {
|
|
58606
59013
|
log$6(`Order ${orderId} not found`, { type: "error" });
|
|
58607
|
-
throw new Error(`Order ${orderId} not found`);
|
|
59014
|
+
throw enrichAlpacaError(new Error(`Order ${orderId} not found`), error);
|
|
58608
59015
|
}
|
|
58609
59016
|
log$6(`Failed to cancel order ${orderId}: ${errorMessage}`, {
|
|
58610
59017
|
type: "error",
|
|
58611
59018
|
});
|
|
58612
|
-
throw new Error(`Failed to cancel order ${orderId}: ${errorMessage}`);
|
|
59019
|
+
throw enrichAlpacaError(new Error(`Failed to cancel order ${orderId}: ${errorMessage}`), error);
|
|
58613
59020
|
}
|
|
58614
59021
|
}
|
|
58615
59022
|
/**
|
|
@@ -58652,7 +59059,7 @@ async function cancelAllOrders(client) {
|
|
|
58652
59059
|
catch (error) {
|
|
58653
59060
|
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
58654
59061
|
log$6(`Failed to cancel all orders: ${errorMessage}`, { type: "error" });
|
|
58655
|
-
throw new Error(`Failed to cancel all orders: ${errorMessage}`);
|
|
59062
|
+
throw enrichAlpacaError(new Error(`Failed to cancel all orders: ${errorMessage}`), error);
|
|
58656
59063
|
}
|
|
58657
59064
|
}
|
|
58658
59065
|
/**
|
|
@@ -58710,16 +59117,16 @@ async function replaceOrder(client, orderId, params) {
|
|
|
58710
59117
|
log$6(`Order ${orderId} cannot be replaced (may already be filled)`, {
|
|
58711
59118
|
type: "error",
|
|
58712
59119
|
});
|
|
58713
|
-
throw new Error(`Order ${orderId} cannot be replaced: order may already be filled or canceled`);
|
|
59120
|
+
throw enrichAlpacaError(new Error(`Order ${orderId} cannot be replaced: order may already be filled or canceled`), error);
|
|
58714
59121
|
}
|
|
58715
59122
|
if (errorMessage.includes("404")) {
|
|
58716
59123
|
log$6(`Order ${orderId} not found`, { type: "error" });
|
|
58717
|
-
throw new Error(`Order ${orderId} not found`);
|
|
59124
|
+
throw enrichAlpacaError(new Error(`Order ${orderId} not found`), error);
|
|
58718
59125
|
}
|
|
58719
59126
|
log$6(`Failed to replace order ${orderId}: ${errorMessage}`, {
|
|
58720
59127
|
type: "error",
|
|
58721
59128
|
});
|
|
58722
|
-
throw new Error(`Failed to replace order ${orderId}: ${errorMessage}`);
|
|
59129
|
+
throw enrichAlpacaError(new Error(`Failed to replace order ${orderId}: ${errorMessage}`), error);
|
|
58723
59130
|
}
|
|
58724
59131
|
}
|
|
58725
59132
|
/**
|
|
@@ -58808,7 +59215,7 @@ async function getOrderByClientId(client, clientOrderId) {
|
|
|
58808
59215
|
log$6(`Failed to fetch order by client_order_id ${clientOrderId}: ${errorMessage}`, {
|
|
58809
59216
|
type: "error",
|
|
58810
59217
|
});
|
|
58811
|
-
throw new Error(`Failed to fetch order by client_order_id ${clientOrderId}: ${errorMessage}`);
|
|
59218
|
+
throw enrichAlpacaError(new Error(`Failed to fetch order by client_order_id ${clientOrderId}: ${errorMessage}`), error);
|
|
58812
59219
|
}
|
|
58813
59220
|
}
|
|
58814
59221
|
|
|
@@ -71631,5 +72038,5 @@ const adaptic = {
|
|
|
71631
72038
|
};
|
|
71632
72039
|
const adptc = adaptic;
|
|
71633
72040
|
|
|
71634
|
-
export { API_RETRY_CONFIGS, AVNewsArticleSchema, AVNewsResponseSchema, AdapticUtilsError, AlpacaAccountDetailsSchema, AlpacaApiError, AlpacaBarSchema, AlpacaClient, AlpacaCryptoBarsResponseSchema, AlpacaHistoricalBarsResponseSchema, AlpacaLatestBarsResponseSchema, AlpacaLatestQuotesResponseSchema, AlpacaLatestTradesResponseSchema, AlpacaMarketDataAPI, AlpacaNewsArticleSchema, AlpacaNewsResponseSchema, AlpacaOrderSchema, AlpacaOrdersArraySchema, AlpacaPortfolioHistoryResponseSchema, AlpacaPositionSchema, AlpacaPositionsArraySchema, AlpacaQuoteSchema, AlpacaTradeSchema, AlpacaTradingAPI, AlphaVantageError, AlphaVantageQuoteResponseSchema, AssetAllocationEngine, AuthenticationError, AutonomyMode, BTC_PAIRS, BarError, CircuitOpenError, CryptoDataError, CryptoOrderError, DEFAULT_CACHE_OPTIONS, DEFAULT_RISK_FREE_RATE, DEFAULT_TIMEOUTS, DEFAULT_TRADING_POLICY, DataFormatError, DecisionMemoryOutcome, DecisionOutcome, DecisionRecordStatus, DuplicateClientOrderIdError, HttpClientError, HttpServerError, KEEP_ALIVE_DEFAULTS, LlmProvider, MARKET_DATA_API, MassiveAggregatesResponseSchema, MassiveApiError, MassiveDailyOpenCloseSchema, MassiveErrorResponseSchema, MassiveGroupedDailyResponseSchema, MassiveLastTradeResponseSchema, MassiveTickerDetailsResponseSchema, MassiveTickerInfoSchema, MassiveTradeSchema as MassiveTradeZodSchema, MassiveTradesResponseSchema, NetworkError, NewsError, OptionStrategyError, OptionsDataError, OverlaySeverity, OverlayStatus, OverlayType, QuoteError, RISK_FREE_RATE_TTL_MS, RateLimitError, RawMassivePriceDataSchema, StampedeProtectedCache, TRADING_API, TimeoutError, TokenBucketRateLimiter, TradeError, TrailingStopValidationError, USDC_PAIRS, USDT_PAIRS, USD_PAIRS, UnsupportedBrokerError, ValidationError, ValidationResponseError, WEBSOCKET_STREAMS, WebSocketError, account, adaptic, adptc, alpaca, analyzeBars, approximateImpliedVolatility, atrNs as atr, bracketOrders, buildOCCSymbol, buildOptionSymbol, buyCryptoNotional, buyToClose, buyToOpen, buyWithStopLoss, buyWithTrailingStop, calculateMoneyness, calculateOrderValue, calculatePeriodPerformance, calculatePutCallRatio, calculateTotalFilledValue, cancelAllCryptoOrders, cancelOCOOrder, cancelOTOOrder, cancelTrailingStop, cancelTrailingStopsForSymbol, checkTradingEligibility, clearClientCache, clock, closeAllOptionPositions, closeOptionPosition, createAlpacaClient, createAlpacaMarketDataAPI, createAlpacaTradingAPI, createBracketOrder, createBrokerClient, createButterflySpread, createClientFromEnv, createCoveredCall, createCryptoLimitOrder, createCryptoMarketOrder, createCryptoOrder, createCryptoStopLimitOrder, createCryptoStopOrder, createExecutorFromTradingAPI, createIronCondor$1 as createIronCondor, createIronCondor as createIronCondorAdvanced, createMultiLegOptionOrder, createOCOOrder, createOTOOrder, createOptionOrder, createPortfolioTrailingStops, createProtectiveBracket, createStampedeProtectedCache, createStraddle$1 as createStraddle, createStraddle as createStraddleAdvanced, createStrangle$1 as createStrangle, createStrangle as createStrangleAdvanced, createStreamManager, createTimeoutSignal, createTrailingStop, createVerticalSpread$1 as createVerticalSpread, createVerticalSpread as createVerticalSpreadAdvanced, entryWithPercentStopLoss, exerciseOption, extractGreeks, filterByExpiration, filterByStrike, filterByType, filterOrdersByDateRange, findATMOptions, findATMStrikes, findNearestExpiration, findOptionsByDelta, formatOrderForLog, formatOrderSummary, generateOptimalAllocation, getAccountConfiguration, getAccountDetails, getAccountSummary, getAgentPoolStatus, getAllOrders, getAlpacaCalendar, getAlpacaClock, getAverageDailyVolume, getBars, getBuyingPower, getCachedRiskFreeRateSync, getCachedRiskFreeRateSyncWithProvenance, getCrypto24HourChange, getCryptoBars, getCryptoDailyPrices, getCryptoPairsByQuote, getCryptoPrice, getCryptoSnapshots, getCryptoSpread, getCryptoStreamUrl, getCryptoTrades, getCurrentPrice, getCurrentPrices, getDailyPrices, getDailyReturns, getDaysToExpiration, getDefaultRiskProfile, getEquityCurve, getExpirationDates, getFilledOrders, getGroupedOptionChain, getHistoricalOptionsBars, getHistoricalTrades, getIntradayPrices, getLatestBars, getLatestCryptoQuotes, getLatestCryptoTrades, getLatestNews, getLatestOptionsQuotes, getLatestOptionsTrades, getLatestQuote, getLatestQuotes, getLatestTrade, getLatestTrades, getLogger, getMarginInfo, getNews, getNewsForSymbols, getOCOOrderStatus, getOTOOrderStatus, getOpenCryptoOrders, getOpenOrders$1 as getOpenOrdersQuery, getOpenTrailingStops, getOptionChain, getOptionContract, getOptionContracts, getOptionSpread, getOptionsChain, getOptionsSnapshots, getOptionsStreamUrl, getOptionsTradingLevel, getOrderHistory, getOrdersBySymbol, getPDTStatus, getPopularCryptoPairs, getPortfolioHistory, getPreviousClose, getPriceRange, getRiskFreeRate, getRiskFreeRateWithProvenance, getSpread, getSpreads, getStockStreamUrl, getStrikePrices, getSupportedCryptoPairs, getSymbolSentiment, getTimeout, getTradeVolume, getTradingApiUrl, getTradingWebSocketUrl, getTrailingStopHWM, groupOrdersByStatus, groupOrdersBySymbol, hasActiveTrailingStop, hasGoodLiquidity as hasOptionLiquidity, hasGoodLiquidity$1 as hasStockLiquidity, hasSufficientVolume, httpAgent, httpsAgent, isAlpacaBrokerCredentials, isContractTradable, isCryptoPair, isExpiringWithin, isMarginAccount, isOptionOrderCancelable, isOptionOrderTerminal, isOrderFillable, isOrderFilled, isOrderOpen, isOrderTerminal$1 as isOrderTerminalStatus, isSupportedCryptoPair, isTransientNetworkError, index$1 as legacyApi, limitBuyWithTakeProfit, ocoOrders, orderUtils, otoOrders, paginate, paginateAll, parseOCCSymbol, protectLongPosition, protectShortPosition, rateLimiters, resetLogger, resetRiskFreeRateCache, riskNs as risk, rollOptionPosition, roundPriceForAlpaca$3 as roundPriceForAlpaca, roundPriceForAlpacaNumber, safeValidateResponse, searchNews, sellAllCrypto, sellCryptoNotional, sellToClose, sellToOpen, setLogger, setRiskFreeRate, shortWithStopLoss, sortOrdersByDate, strategyNs as strategy, index as tradingPolicy, trailingStops, updateAccountConfiguration, updateTrailingStop, validateAlpacaCredentials, validateAlphaVantageApiKey, validateMassiveApiKey$1 as validateMassiveApiKey, validateMultiLegOrder, validateResponse, verifyFetchKeepAlive, volatilityNs as volatility, waitForOrderFill, withRetry, withTimeout };
|
|
72041
|
+
export { API_RETRY_CONFIGS, AVNewsArticleSchema, AVNewsResponseSchema, AdapticUtilsError, AlpacaAccountDetailsSchema, AlpacaApiError, AlpacaBarSchema, AlpacaClient, AlpacaCryptoBarsResponseSchema, AlpacaHistoricalBarsResponseSchema, AlpacaLatestBarsResponseSchema, AlpacaLatestQuotesResponseSchema, AlpacaLatestTradesResponseSchema, AlpacaMarketDataAPI, AlpacaNewsArticleSchema, AlpacaNewsResponseSchema, AlpacaOrderSchema, AlpacaOrdersArraySchema, AlpacaPortfolioHistoryResponseSchema, AlpacaPositionSchema, AlpacaPositionsArraySchema, AlpacaQuoteSchema, AlpacaTradeSchema, AlpacaTradingAPI, AlphaVantageError, AlphaVantageQuoteResponseSchema, AssetAllocationEngine, AuthenticationError, AutonomyMode, BTC_PAIRS, BarError, CircuitOpenError, CryptoDataError, CryptoOrderError, DEFAULT_CACHE_OPTIONS, DEFAULT_RISK_FREE_RATE, DEFAULT_TIMEOUTS, DEFAULT_TRADING_POLICY, DataFormatError, DecisionMemoryOutcome, DecisionOutcome, DecisionRecordStatus, DuplicateClientOrderIdError, HttpClientError, HttpServerError, KEEP_ALIVE_DEFAULTS, LlmProvider, MARKET_DATA_API, MassiveAggregatesResponseSchema, MassiveApiError, MassiveDailyOpenCloseSchema, MassiveErrorResponseSchema, MassiveGroupedDailyResponseSchema, MassiveLastTradeResponseSchema, MassiveTickerDetailsResponseSchema, MassiveTickerInfoSchema, MassiveTradeSchema as MassiveTradeZodSchema, MassiveTradesResponseSchema, NetworkError, NewsError, OptionStrategyError, OptionsDataError, OverlaySeverity, OverlayStatus, OverlayType, QuoteError, RISK_FREE_RATE_TTL_MS, RateLimitError, RawMassivePriceDataSchema, StampedeProtectedCache, TRADING_API, TimeoutError, TokenBucketRateLimiter, TradeError, TrailingStopValidationError, USDC_PAIRS, USDT_PAIRS, USD_PAIRS, UnsupportedBrokerError, ValidationError, ValidationResponseError, WEBSOCKET_STREAMS, WebSocketError, account, adaptic, adptc, alpaca, analyzeBars, approximateImpliedVolatility, atrNs as atr, bracketOrders, buildOCCSymbol, buildOptionSymbol, buyCryptoNotional, buyToClose, buyToOpen, buyWithStopLoss, buyWithTrailingStop, calculateMoneyness, calculateOrderValue, calculatePeriodPerformance, calculatePutCallRatio, calculateTotalFilledValue, cancelAllCryptoOrders, cancelOCOOrder, cancelOTOOrder, cancelTrailingStop, cancelTrailingStopsForSymbol, checkTradingEligibility, clearClientCache, clock, closeAllOptionPositions, closeOptionPosition, createAlpacaClient, createAlpacaMarketDataAPI, createAlpacaTradingAPI, createBracketOrder, createBrokerClient, createButterflySpread, createClientFromEnv, createCoveredCall, createCryptoLimitOrder, createCryptoMarketOrder, createCryptoOrder, createCryptoStopLimitOrder, createCryptoStopOrder, createExecutorFromTradingAPI, createIronCondor$1 as createIronCondor, createIronCondor as createIronCondorAdvanced, createMultiLegOptionOrder, createOCOOrder, createOTOOrder, createOptionOrder, createPortfolioTrailingStops, createProtectiveBracket, createStampedeProtectedCache, createStraddle$1 as createStraddle, createStraddle as createStraddleAdvanced, createStrangle$1 as createStrangle, createStrangle as createStrangleAdvanced, createStreamManager, createTimeoutSignal, createTrailingStop, createVerticalSpread$1 as createVerticalSpread, createVerticalSpread as createVerticalSpreadAdvanced, enrichAlpacaError, entryWithPercentStopLoss, exerciseOption, extractAlpacaBrokerError, extractGreeks, filterByExpiration, filterByStrike, filterByType, filterOrdersByDateRange, findATMOptions, findATMStrikes, findNearestExpiration, findOptionsByDelta, formatOrderForLog, formatOrderSummary, generateOptimalAllocation, getAccountConfiguration, getAccountDetails, getAccountSummary, getAgentPoolStatus, getAllOrders, getAlpacaBrokerErrorCode, getAlpacaBrokerErrorDetail, getAlpacaCalendar, getAlpacaClock, getAverageDailyVolume, getBars, getBuyingPower, getCachedRiskFreeRateSync, getCachedRiskFreeRateSyncWithProvenance, getCrypto24HourChange, getCryptoBars, getCryptoDailyPrices, getCryptoPairsByQuote, getCryptoPrice, getCryptoSnapshots, getCryptoSpread, getCryptoStreamUrl, getCryptoTrades, getCurrentPrice, getCurrentPrices, getDailyPrices, getDailyReturns, getDaysToExpiration, getDefaultRiskProfile, getEquityCurve, getExpirationDates, getFilledOrders, getGroupedOptionChain, getHistoricalOptionsBars, getHistoricalTrades, getIntradayPrices, getLatestBars, getLatestCryptoQuotes, getLatestCryptoTrades, getLatestNews, getLatestOptionsQuotes, getLatestOptionsTrades, getLatestQuote, getLatestQuotes, getLatestTrade, getLatestTrades, getLogger, getMarginInfo, getNews, getNewsForSymbols, getOCOOrderStatus, getOTOOrderStatus, getOpenCryptoOrders, getOpenOrders$1 as getOpenOrdersQuery, getOpenTrailingStops, getOptionChain, getOptionContract, getOptionContracts, getOptionSpread, getOptionsChain, getOptionsSnapshots, getOptionsStreamUrl, getOptionsTradingLevel, getOrderHistory, getOrdersBySymbol, getPDTStatus, getPopularCryptoPairs, getPortfolioHistory, getPreviousClose, getPriceRange, getRiskFreeRate, getRiskFreeRateWithProvenance, getSpread, getSpreads, getStockStreamUrl, getStrikePrices, getSupportedCryptoPairs, getSymbolSentiment, getTimeout, getTradeVolume, getTradingApiUrl, getTradingWebSocketUrl, getTrailingStopHWM, groupOrdersByStatus, groupOrdersBySymbol, hasActiveTrailingStop, hasGoodLiquidity as hasOptionLiquidity, hasGoodLiquidity$1 as hasStockLiquidity, hasSufficientVolume, httpAgent, httpsAgent, isAlpacaBrokerCredentials, isContractTradable, isCryptoPair, isExpiringWithin, isMarginAccount, isOptionOrderCancelable, isOptionOrderTerminal, isOrderFillable, isOrderFilled, isOrderOpen, isOrderTerminal$1 as isOrderTerminalStatus, isSupportedCryptoPair, isTransientNetworkError, index$1 as legacyApi, limitBuyWithTakeProfit, ocoOrders, orderUtils, otoOrders, paginate, paginateAll, parseOCCSymbol, protectLongPosition, protectShortPosition, rateLimiters, resetLogger, resetRiskFreeRateCache, riskNs as risk, rollOptionPosition, roundPriceForAlpaca$3 as roundPriceForAlpaca, roundPriceForAlpacaNumber, safeValidateResponse, searchNews, sellAllCrypto, sellCryptoNotional, sellToClose, sellToOpen, setLogger, setRiskFreeRate, shortWithStopLoss, sortOrdersByDate, strategyNs as strategy, index as tradingPolicy, trailingStops, updateAccountConfiguration, updateTrailingStop, validateAlpacaCredentials, validateAlphaVantageApiKey, validateMassiveApiKey$1 as validateMassiveApiKey, validateMultiLegOrder, validateResponse, verifyFetchKeepAlive, volatilityNs as volatility, waitForOrderFill, withRetry, withTimeout };
|
|
71635
72042
|
//# sourceMappingURL=index.mjs.map
|