### Install Dependencies and Run Scripts Source: https://github.com/bennycode/trading-signals/blob/main/README.md Installs project dependencies and provides commands to run tests, launch the indicator showcase, or start the Telegram bot. Ensure TELEGRAM_BOT_TOKEN is set in your environment to start the bot. ```bash npm install # Run the full test matrix across all packages npm test # Launch the indicator showcase (Next.js) npm run start:docs # Start the Telegram bot (requires TELEGRAM_BOT_TOKEN in your env) npm run start:bot ``` -------------------------------- ### Build Documentation Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-signals/README.md Run this command to build and run the documentation for the trading-signals package. Ensure you have npm installed. ```bash npm run docs ``` -------------------------------- ### Install trading-signals Package Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-signals/README.md Install the trading-signals library using npm. ```bash npm install trading-signals ``` -------------------------------- ### Install Trading Strategies Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-strategies/README.md Install the trading-strategies library using npm. This command is used to add the package to your project's dependencies. ```bash npm install trading-strategies ``` -------------------------------- ### ProtectedStrategy Configuration Example Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-strategies/src/strategy-protected/README.md This JSON structure shows how to configure stop-loss and take-profit settings within the 'protected' key. It demonstrates mutually exclusive trigger variants and order types. ```json { "protected": { "stopLossPct": "5", "stopLossOrder": "market", "takeProfitNominal": "10" }, "mySubclassField": "whatever your strategy needs" } ``` -------------------------------- ### Running Backtest for ScalpStrategy on AMD Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-strategies/src/strategy-scalp/README.md This command runs a backtest for the ScalpStrategy using AMD historical data. Ensure you have the necessary data file and strategy package installed. ```bash npm run backtest -- \ --data src/backtest/candles/AMD_USD_2026_Q1_3_months.json \ --strategy '@typedtrader/strategy-scalp' ``` -------------------------------- ### Get Alpaca Client Source: https://github.com/bennycode/trading-signals/blob/main/packages/exchange/README.md Initializes the Alpaca exchange client. Ensure your Alpaca API keys and secrets are set as environment variables. ```typescript import {getAlpacaClient} from '@typedtrader/exchange'; const exchange = getAlpacaClient({ apiKey: process.env.ALPACA_API_KEY, apiSecret: process.env.ALPACA_API_SECRET, usePaperTrading: true, }); ``` -------------------------------- ### Mapper Layer Translation Example Source: https://github.com/bennycode/trading-signals/blob/main/packages/exchange/BROKER_TEMPLATE.md Illustrates the role of a dedicated mapper class (`XxxBrokerMapper`) in translating between the broker's wire format and the neutral domain types used throughout the package. ```typescript class AlpacaBrokerMapper { toNeutralOrder(wireOrder: AlpacaOrderWire): Order { // ... translation logic ... return { id: wireOrder.id, side: wireOrder.side === 'buy' ? OrderSide.BUY : OrderSide.SELL, // ... other fields }; } toWireOrder(order: Order): AlpacaOrderWire { // ... translation logic ... return { id: order.id, side: order.side === OrderSide.BUY ? 'buy' : 'sell', // ... other fields }; } } ``` -------------------------------- ### Get Required Inputs for Indicator Stability Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-signals/README.md Demonstrates using the `getRequiredInputs()` method to determine the minimum number of data points an indicator needs before it can produce a stable result. This is useful for validation and understanding indicator behavior. ```typescript import {SMA, EMA, RSI} from 'trading-signals'; const sma = new SMA(5); console.log(sma.getRequiredInputs()); // 5 ``` -------------------------------- ### Get Trading Signal State Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-signals/README.md Use the getSignal() method to retrieve the current trading signal state and detect changes. This is useful for identifying potential trading opportunities with indicators like RSI. ```typescript import {RSI} from 'trading-signals'; const rsi = new RSI(14); // Add price data // ... // Get the trading signal const signal = rsi.getSignal(); console.log(signal.state); // "BEARISH", "BULLISH", "SIDEWAYS", or "UNKNOWN" console.log(signal.hasChanged); // true if the signal state changed from the previous value ``` -------------------------------- ### Axios Retry Condition Example Source: https://github.com/bennycode/trading-signals/blob/main/packages/exchange/BROKER_TEMPLATE.md Defines a condition for retrying requests, including network errors and specific HTTP status codes like 429 (Too Many Requests). It short-circuits permanent business errors. ```javascript function retryCondition(error) { // Consider the following conditions: // - Network errors // - HTTP 429 (Too Many Requests) // - Vendor-specific transient error codes // Short-circuit permanent business errors (e.g., auth failed, invalid input) return true; } ``` -------------------------------- ### Build Trading Strategies Package Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-signals-docs/README.md Use this command to build the trading-strategies package after making changes. This is necessary for the changes to be reflected in the documentation site. ```bash lerna run dist --scope trading-strategies ``` -------------------------------- ### BuyOnce Strategy Configuration Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-strategies/README.md Configuration for the BuyOnce strategy. It can buy immediately or at a specified limit price, and supports quantity or spend-based sizing. Stop-loss and take-profit guards can be added. ```json { "buyAt": "95", "spend": "500", "protected": { "stopLossPct": "5", "takeProfitPct": "10" } } ``` -------------------------------- ### Running Backtest for ScalpStrategy on INTC Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-strategies/src/strategy-scalp/README.md This command executes a backtest for the ScalpStrategy with INTC historical data. Verify that the data file path and strategy name are correct. ```bash npm run backtest -- \ --data src/backtest/candles/INTC_USD_2026_Q1_3_months.json \ --strategy '@typedtrader/strategy-scalp' ``` -------------------------------- ### Build Trading Signals Package Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-signals-docs/README.md Use this command to build the trading-signals package after making changes. This is necessary for the changes to be reflected in the documentation site. ```bash lerna run dist --scope trading-signals ``` -------------------------------- ### Rebuild Upstream Packages Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-signals-docs/CLAUDE.md Run these commands to rebuild the exchange and trading-strategies packages if type errors related to stale types are encountered. ```bash npm run build --workspace=packages/exchange npm run build --workspace=packages/trading-strategies ``` -------------------------------- ### Add Trading Strategy via Command Source: https://github.com/bennycode/trading-signals/blob/main/packages/messaging/README.md Use the /strategyAdd command to attach a trading strategy to an account. Specify the account ID, trading pair, and configuration in JSON format. ```bash /strategyAdd 1 AAPL,USD {"protected":{"stopLossPct":"5","takeProfitPct":"10","seedFromBalance":true}} ``` -------------------------------- ### Axios Client Configuration with Retry Source: https://github.com/bennycode/trading-signals/blob/main/packages/exchange/BROKER_TEMPLATE.md Sets up an Axios client with base URL and applies retry logic for transient errors. Ensures robust handling of network issues and rate limiting. ```javascript import axios from "axios"; import axiosRetry from "axios-retry"; const client = axios.create({ baseURL }); axiosRetry(client, { retries: Infinity, retryCondition, retryDelay: retryCount => retryCount * 1_000, }); ``` -------------------------------- ### Extending ProtectedStrategy in TypeScript Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-strategies/src/strategy-protected/README.md Demonstrates how to create a new trading strategy by extending `ProtectedStrategy` and merging its schema with custom configuration. Ensure `super.processCandle()` is called to activate kill-switch logic. ```typescript import {z} from 'zod'; import {ProtectedStrategy, ProtectedStrategySchema} from '@typedtrader/trading-strategies'; const MyStrategySchema = ProtectedStrategySchema.extend({ mySetting: z.string(), }); type MyStrategyConfig = z.infer; export class MyStrategy extends ProtectedStrategy { static override NAME = '@typedtrader/strategy-my-strategy'; constructor(config: MyStrategyConfig) { super({ config, state: { /* subclass-specific fields */ }, }); } protected override async processCandle(candle, state) { const guardAdvice = await super.processCandle(candle, state); if (guardAdvice) { return guardAdvice; // kill switch fired — return immediately } // subclass logic goes here } } ``` -------------------------------- ### Trading Signals Project Architecture Diagram Source: https://github.com/bennycode/trading-signals/blob/main/README.md This diagram shows the relationship between the core libraries: trading-signals, trading-strategies, @typedtrader/exchange, and @typedtrader/messaging. It also illustrates how these components interact with external services like exchanges and a visual backtester. ```mermaid graph TD messaging["@typedtrader/messaging (Chatbot)"] messaging --> session["TradingSession (online: pairs a strategy with a broker)"] website["typedtrader.com (Visual Backtester)"] --> backtest["BacktestExecutor (offline: replays historical candles)"] session --> strategies["trading-strategies"] session --> exchange["@typedtrader/exchange"] backtest --> strategies backtest --> exchange strategies --> signals["trading-signals"] signals --> SMA signals --> EMA signals --> BBANDS["Bollinger Bands"] signals --> more["..."] exchange --> Alpaca exchange --> T212["Trading 212"] exchange --> more-exchanges["..."] ``` -------------------------------- ### Import Core Trading Strategy Components Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-strategies/README.md Import the Strategy class and relevant types from the 'trading-strategies' and '@typedtrader/exchange' libraries. These are essential for defining and using trading strategies. ```typescript import {Strategy} from 'trading-strategies'; import {ExchangeOrderSide, ExchangeOrderType} from '@typedtrader/exchange'; import type {OrderAdvice} from '@typedtrader/exchange'; ``` -------------------------------- ### Layered Architecture Overview Source: https://github.com/bennycode/trading-signals/blob/main/packages/exchange/BROKER_TEMPLATE.md Illustrates the hierarchical structure of a broker integration, from the strategy layer down to the underlying transport mechanisms like axios or native WebSockets. ```plaintext Strategy ↓ uses domain types Broker (neutral interface in Broker.ts) ↓ uses mapper Mapper (wire ↔ neutral types) ↓ uses validated data Schema (zod, parses at the boundary) ↓ uses raw response API class (one method per endpoint) ↓ uses configured client RESTClient / WebSocket manager (auth, retries, reconnect) ↓ uses transport axios / native WebSocket ``` -------------------------------- ### Test Inputs and Outputs: Use `as const` and `forEach` Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-signals/CLAUDE.md Use `as const` for both test inputs and expected outputs. When looping, prefer `forEach` over manual index-based `for` loops for better readability and immutability. ```typescript // ❌ Bad: Missing const assertions, so "expectations" can be mutated (values shifted) it('calculates the moving average based on the last 5 prices', () => { const prices = [91, 90, 89, 88, 90]; const expectations = ['89.33']; const wma = new WMA(5); for (const price of prices) { const result = wma.add(price); if (result) { const expected = expectations.shift(); expect(result.toFixed(2)).toBe(expected); } } expect(wma.isStable).toBe(true); }); // ✅ Good: Use readonly arrays and match results using an "offset" it('calculates the moving average based on the last 5 prices', () => { const prices = [91, 90, 89, 88, 90] as const; const expectations = ['89.33'] as const; const wma = new WMA(5); const offset = wma.getRequiredInputs() - 1; prices.forEach((price, i) => { const result = wma.add(price); if (result) { const expected = expectations[i - offset]; expect(result.toFixed(2)).toBe(expected); } }); expect(wma.isStable).toBe(true); }); ``` -------------------------------- ### Basic SMA Usage and Data Input Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-signals/README.md Demonstrates initializing an SMA indicator, adding individual values, batch updates, replacing values, and checking stability and results. Useful for both historical data processing and live charting. ```typescript import {SMA} from 'trading-signals'; const sma = new SMA(3); // You can add values individually: sma.add(40); sma.add(30); sma.add(20); // You can add multiple values at once: sma.updates([20, 40, 80]); // You can replace a previous value (useful for live charting): sma.replace(40); // You can check if an indicator is stable: console.log(sma.isStable); // true // If an indicator is stable, you can get its result: console.log(sma.getResult()); // 50.0003 // You can also get the result without optional chaining: console.log(sma.getResultOrThrow()); // 50.0003 // Various precisions are available too: console.log(sma.getResultOrThrow().toFixed(2)); // "50.00" console.log(sma.getResultOrThrow().toFixed(4)); // "50.0003" // Each indicator also includes convenient features such as "lowest" and "highest" lifetime values: console.log(sma.lowest?.toFixed(2)); // "23.33" console.log(sma.highest?.toFixed(2)); // "53.33" ``` -------------------------------- ### Indicator Methods: Prefer `add` over `update` Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-signals/CLAUDE.md In test cases, prefer using the convenience methods `add(i)` instead of `update(i, false)` and `replace(i)` instead of `update(i, true)` for better clarity and intent. ```typescript // ❌ Bad: Using `update` directly it('returns null until enough values are provided', () => { const iqr = new IQR(5); for (let i = 0; i < 4; i++) { const result = iqr.update(i, false); expect(result).toBeNull(); } }); // ✅ Good: Using `add` for clarity and intent it('returns null until enough values are provided', () => { const iqr = new IQR(5); for (let i = 0; i < 4; i++) { const result = iqr.add(i); expect(result).toBeNull(); } }); ``` -------------------------------- ### ProtectionOnly Strategy Configuration Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-strategies/README.md Configuration for the ProtectionOnly strategy, which does not open new positions but can attach guards to existing ones using seedFromBalance. Guards are based on a baseline price. ```json { "protected": { "stopLossPct": "5", "takeProfitPct": "10", "seedFromBalance": true } } ``` -------------------------------- ### Validate Strategy Configuration with Zod Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-strategies/README.md Import and use Zod schemas to validate strategy configurations at runtime and infer TypeScript types. This ensures that user-provided configurations conform to the expected structure. ```typescript import {MultiIndicatorConfluenceSchema, type MultiIndicatorConfluenceConfig} from 'trading-strategies'; // Validate user input at runtime const result = MultiIndicatorConfluenceSchema.safeParse(userInput); // Type is inferred automatically from the schema type Config = MultiIndicatorConfluenceConfig; // z.infer ``` -------------------------------- ### Import SMA Indicator (CommonJS) Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-signals/README.md Import the SMA indicator using CommonJS module syntax. ```javascript const {SMA} = require('trading-signals'); ``` -------------------------------- ### Validate Account Existence and Ownership Source: https://github.com/bennycode/trading-signals/blob/main/packages/messaging/CLAUDE.md Use `getAccountOrError` to ensure an account exists and belongs to the specified user. Avoid manual checks with `findByPk` as they can be error-prone and bypass ownership validation. ```typescript const account = getAccountOrError(userId, accountId); ``` ```typescript const account = Account.findByPk(accountId); if (!account) { ... } if (account.userId !== userId) { ... } ``` -------------------------------- ### Import SMA Indicator (ESM) Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-signals/README.md Import the SMA indicator using ECMAScript module syntax. ```typescript import {SMA} from 'trading-signals'; ``` -------------------------------- ### Testing `replace()`: Verify Bidirectional Replacement Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-signals/CLAUDE.md When testing the `replace()` method, verify bidirectional replacement by testing original vs replaced values and then restoring back to the original. ```typescript // ❌ Bad: Only tests that replace changes the value it('can replace recently added values', () => { const stoch = new StochasticOscillator(5, 3, 3); for (let i = 0; i < 9; i++) { stoch.add({close: 50 + i, high: 100, low: 10}); } const resultBefore = stoch.getResultOrThrow(); stoch.add({close: 80, high: 100, low: 10}); stoch.replace({close: 30, high: 100, low: 10}); const resultAfter = stoch.getResultOrThrow(); expect(resultAfter.stochK).not.toBe(resultBefore.stochK); }); ``` -------------------------------- ### Test Clarity: Direct IQR Calculation Assertion Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-signals/CLAUDE.md Pass all values directly to the IQR calculation and assert the expected value clearly. Avoid slicing arrays or using complex boolean conditions for assertions. ```typescript // ❌ Bad: The test slices the input array and uses a boolean condition to assert the result, // which makes the intent less clear and harder to debug. it('correctly calculates the IQR', () => { const prices = [7, 7, 31, 31, 47, 75, 87, 115, 116, 119, 119, 155, 177]; const iqr = new IQR(13); for (const v of values.slice(0, -1)) { iqr.update(v, false); } const result = iqr.update(values.at(-1)!, false); expect(result).toBe(88); }); // ✅ Good: All values are passed in clearly, and the expected IQR value is asserted directly, // making the test easier to understand and maintain. it('correctly calculates the IQR', () => { const prices = [7, 7, 31, 31, 47, 75, 87, 115, 116, 119, 119, 155, 177]; const iqr = new IQR(13); for (const value of values) { iqr.add(value); } expect(iqr.getResultOrThrow()).toBe(88); }); ``` -------------------------------- ### Properly Update Indicator Results with setResult Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-signals/CLAUDE.md Demonstrates the correct method for updating indicator results using `setResult()` to ensure proper signal tracking. Avoid direct assignment to `this.result`. ```typescript // ❌ Bad: Direct assignment breaks signal tracking override update(candle: HighLowClose, replace: boolean) { // ... calculation logic ... return (this.result = calculatedValue); } ``` ```typescript // ✅ Good: Using setResult() properly maintains previousResult for signal tracking override update(candle: HighLowClose, replace: boolean) { // ... calculation logic ... return this.setResult(calculatedValue, replace); } ``` -------------------------------- ### Broker-Prefixed Schema and Type Naming Source: https://github.com/bennycode/trading-signals/blob/main/packages/exchange/BROKER_TEMPLATE.md Prefixes vendor-specific enums and schemas with the broker name (e.g., `AlpacaOrderStatus`) to avoid collisions with neutral domain types and clarify the origin of the data. ```javascript // Example for Alpaca specific status export enum AlpacaOrderStatus { NEW = "new", FILLED = "filled", // ... other statuses } // Neutral domain type export enum OrderStatus { OPEN, CLOSED, // ... other statuses } ``` -------------------------------- ### Test Descriptions: State What Code Does Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-signals/CLAUDE.md Avoid using 'should' in test descriptions. Instead, write a clear statement of what the code actually does. ```typescript // ❌ Bad: Describes what the code "should" do it('should return 1 for a bullish setup', () => {}); // ✅ Good: Describes what the code "does" it('returns 1 for a bullish setup', () => {}); ``` -------------------------------- ### Trading212 Broker with Alpaca Market Data Source: https://github.com/bennycode/trading-signals/blob/main/packages/exchange/README.md Configures the Trading212 broker to use Alpaca for market data. This is necessary because Trading212 lacks its own historical bars and WebSocket feed. Symbol mapping is handled automatically. ```typescript import {AlpacaMarketData, getTrading212Client, TradingPair} from '@typedtrader/exchange'; // 1. Construct an Alpaca-backed market-data source. const marketData = new AlpacaMarketData({ apiKey: 'ALPACA_API_KEY', apiSecret: 'ALPACA_API_SECRET', usePaperTrading: false, // read-only; doesn't place orders }); // 2. Wire it into the Trading212 broker. const broker = getTrading212Client({ apiKey: 'TRADING212_API_KEY', apiSecret: 'TRADING212_API_SECRET', usePaperTrading: true, marketData, // required — Trading212 has no candles of its own }); // 3. Use the broker as if it provided everything natively. Symbol mapping is automatic: // Trading212's `AAPL_US_EQ` is stripped to Alpaca's `AAPL` behind the scenes. const pair = new TradingPair('AAPL_US_EQ', 'USD'); const latest = await broker.getLatestCandle(pair, 60_000); // → from Alpaca's WebSocket await broker.placeLimitOrder(pair, {side: 'BUY', size: '1', price: latest.close}); // → Trading212 ``` -------------------------------- ### Handling NotEnoughDataError with getResultOrThrow Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-signals/README.md Illustrates how to use a try-catch block with `getResultOrThrow()` to handle cases where an indicator has not yet received the minimum required data. This is crucial for robust error handling in streaming data scenarios. ```typescript import {SMA} from 'trading-signals'; // Our interval is 3, so we need 3 input values const sma = new SMA(3); // We supply 2 input values sma.add(10); sma.add(40); try { // We will get an error, because the minimum amount of inputs is 3 sma.getResultOrThrow(); } catch (error) { console.log(error.constructor.name); // "NotEnoughDataError" } // We will supply the 3rd input value sma.add(70); // Now, we will receive a proper result console.log(sma.getResultOrThrow()); // 40 ``` -------------------------------- ### Test Stochastic Oscillator Replacement Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-signals/CLAUDE.md Verifies that the replace functionality correctly updates the indicator's state and allows for restoration to a previous state. ```typescript // ✅ Good: Tests replacement and restoration to verify replace functionality it('replaces the most recently added value', () => { const stoch = new StochasticOscillator(5, 3, 3); for (let i = 0; i < 9; i++) { stoch.add({close: 50 + i, high: 100, low: 10}); } const originalValue = {close: 80, high: 100, low: 10} as const; const replacedValue = {close: 30, high: 100, low: 10} as const; const originalResult = stoch.add(originalValue); const replacedResult = stoch.replace(replacedValue); expect(replacedResult?.stochK).not.toBe(originalResult?.stochK); const restoredResult = stoch.replace(originalValue); expect(restoredResult?.stochK).toBe(originalResult?.stochK); }); ``` -------------------------------- ### Code Readability: Blank Lines Around Control Statements Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-signals/CLAUDE.md Add blank lines before and after control statements like for-loops to improve visual separation and readability. ```typescript // ❌ Bad: For-statement is tied to variable declaration const td = new TDS(); for (let i = 0; i < 5; i++) { td.add(i); } // ✅ Good: Visual space between variable declaration and for-statement const td = new TDS(); for (let i = 0; i < 5; i++) { td.add(i); } ``` -------------------------------- ### Method Signature: Infer Return Types Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-signals/CLAUDE.md Prefer inferred return types over explicit return types to keep code cleaner and reduce duplication. ```typescript // ❌ Bad: Explicit return type override update(data: HighLowCloseVolume, replace: boolean) { } // ✅ Good: Let TypeScript infer the return type override update(data: HighLowCloseVolume, replace: boolean) { } ``` -------------------------------- ### Protected State Schema Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-strategies/src/strategy-protected/README.md Defines the structure of the persisted protected state for a trading strategy, including kill-switch status and position tracking metrics. ```typescript { killed: boolean; // has a guard fired? killedReason: string | null; killedOrderType: 'limit' | 'market' | null; // which order type the kill switch uses killedLimitPrice: string | null; // target limit price for retries (null for market) totalCostBasis: string; totalPositionSize: string; } ``` -------------------------------- ### Log Clarity: Wrap Variables in Quotes Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-signals/CLAUDE.md Wrap interpolated variables in quotes within log messages to make their values stand out and improve readability. ```typescript // ❌ Bad: Interpolated values blend into the message console.log(`Account with ID ${accountId} not found`); // ✅ Good: Quotes make variable values stand out console.log(`Account with ID "${accountId}" not found`); ``` -------------------------------- ### API Class Endpoint URL Definition Source: https://github.com/bennycode/trading-signals/blob/main/packages/exchange/BROKER_TEMPLATE.md Defines static URL constants within an API class for specific endpoints. This centralizes endpoint definitions for easier management and use in retry configurations. ```javascript class OrderAPI { static URL = { ORDERS: '/orders', // ... other endpoints }; // ... methods } ``` -------------------------------- ### Zod Schema for Loose Object Parsing Source: https://github.com/bennycode/trading-signals/blob/main/packages/exchange/BROKER_TEMPLATE.md Uses `z.looseObject()` to create Zod schemas that tolerate extra fields from vendors, preventing parsing errors when the API response structure changes. ```javascript import { z } from "zod"; export const BarSchema = z.looseObject({ // schema fields here }); export type Bar = z.infer; ``` -------------------------------- ### Axios Request Interceptor for Authentication Source: https://github.com/bennycode/trading-signals/blob/main/packages/exchange/BROKER_TEMPLATE.md Implements authentication logic within an Axios request interceptor. This is flexible for token refresh, signing, and handling clock skew. ```javascript httpClient.interceptors.request.use(async (config) => { // Add authentication headers, refresh tokens, etc. return config; }); ``` -------------------------------- ### Class Definition: Avoid Redundant Generic Type Arguments Source: https://github.com/bennycode/trading-signals/blob/main/packages/trading-signals/CLAUDE.md Avoid explicitly specifying generic type parameters when a default is already provided by the base class. ```typescript // ❌ Bad: Redundant generic type argument export class IQR extends IndicatorSeries {} // ✅ Good: Rely on the default generic export class IQR extends IndicatorSeries {} ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.