1Branch0Tags
GL
glucryptoFix Paragon perp market resolution
251fe3214 days ago5Commits
typescript
import { z } from "zod"; export const TEMPLATE_CONFIG_SCHEMA = { type: "object", "x-budget": { modeField: "allocationMode", defaultMode: "target_notional", title: "Budget & allocation", description: "Core exposure settings are shown first.", modes: { target_notional: { fields: ["targetNotionalUsd", "hedgeRatio"], }, }, }, required: [ "platform", "allocationMode", "legAAsset", "legBAsset", "legAMarketType", "legBMarketType", "legASide", "targetNotionalUsd", "hedgeRatio", "legALeverage", "legBLeverage", "legALeverageMode", "legBLeverageMode", "slippageBps", "rebalanceDriftPct", "environment", ], properties: { configVersion: { type: "number", title: "Config version", description: "Internal version for pair-trade config defaults.", readOnly: true, "x-hidden": true, "x-section": "Meta", "x-order": 1000, }, platform: { type: "string", enum: ["hyperliquid"], title: "Platform", description: "Execution venue for long + short legs.", readOnly: true, "x-section": "Execution", "x-order": 1, }, allocationMode: { type: "string", enum: ["target_notional"], title: "Allocation mode", description: "Canonical sizing mode for pair-trade templates.", readOnly: true, "x-hidden": true, "x-section": "Meta", "x-order": 1001, }, legAAsset: { type: "string", title: "Leg A asset", description: "Primary pair leg asset (example: SOL).", "x-format": "asset", "x-section": "Strategy", "x-order": 1, }, legBAsset: { type: "string", title: "Leg B asset", description: "Opposite pair leg asset (example: ETH).", "x-format": "asset", "x-section": "Strategy", "x-order": 2, }, legAMarketType: { type: "string", enum: ["spot", "perp"], title: "Leg A market", description: "Market type for Leg A.", "x-enumLabels": ["Spot", "Perp"], "x-section": "Strategy", "x-order": 3, }, legBMarketType: { type: "string", enum: ["spot", "perp"], title: "Leg B market", description: "Market type for Leg B.", "x-enumLabels": ["Spot", "Perp"], "x-section": "Strategy", "x-order": 4, }, legASide: { type: "string", enum: ["long", "short"], title: "Leg A side", description: "Whether Leg A is the long or short side. Leg B uses the opposite side.", "x-enumLabels": ["Long", "Short"], "x-section": "Strategy", "x-order": 5, }, targetNotionalUsd: { type: "number", title: "Leg A notional", description: "USD notional for Leg A before applying the Leg B size ratio.", minimum: 1, "x-unit": "USD", "x-format": "currency", "x-step": 1, "x-section": "Strategy", "x-order": 6, }, hedgeRatio: { type: "number", title: "Leg B notional size", description: "Leg B notional exposure as a multiplier of Leg A notional. This is not leverage.", minimum: 0.01, "x-unit": "x", "x-step": 0.01, "x-section": "Strategy", "x-order": 7, }, legALeverage: { type: "number", title: "Leg A leverage", description: "Margin leverage for Leg A when Leg A is a perp market. This changes margin and liquidation buffer, not notional size.", minimum: 1, maximum: 40, "x-unit": "x", "x-step": 1, "x-section": "Execution", "x-order": 3, }, legBLeverage: { type: "number", title: "Leg B leverage", description: "Margin leverage for Leg B when Leg B is a perp market. This changes margin and liquidation buffer, not notional size.", minimum: 1, maximum: 40, "x-unit": "x", "x-step": 1, "x-section": "Execution", "x-order": 4, }, legALeverageMode: { type: "string", enum: ["cross", "isolated"], title: "Leg A margin mode", description: "Margin mode for Leg A when Leg A is a perp market.", "x-enumLabels": ["Cross", "Isolated"], "x-section": "Execution", "x-order": 5, }, legBLeverageMode: { type: "string", enum: ["cross", "isolated"], title: "Leg B margin mode", description: "Margin mode for Leg B when Leg B is a perp market.", "x-enumLabels": ["Cross", "Isolated"], "x-section": "Execution", "x-order": 6, }, slippageBps: { type: "number", title: "Slippage", description: "Maximum slippage for marketable orders.", minimum: 0, maximum: 5000, "x-unit": "bps", "x-format": "bps", "x-step": 1, "x-section": "Risk limits", "x-order": 1, }, rebalanceDriftPct: { type: "number", title: "Rebalance drift", description: "Percent of target notional before rebalancing either leg.", minimum: 0.1, maximum: 50, "x-unit": "%", "x-format": "percent", "x-step": 0.1, "x-section": "Risk limits", "x-order": 2, }, environment: { type: "string", enum: ["mainnet", "testnet"], title: "Environment", description: "Hyperliquid environment for execution.", "x-enumLabels": ["Mainnet", "Testnet"], "x-section": "Execution", "x-order": 2, }, schedule: { type: ["object", "null"], title: "Schedule", description: "Optional cron schedule for advanced recurring maintenance.", "x-section": "Schedule", properties: { cron: { type: "string", title: "Cron expression", description: "Standard cron expression for the run schedule.", "x-order": 1, }, enabled: { type: "boolean", title: "Enabled", description: "Enable the scheduled rebalance.", "x-order": 2, }, notifyEmail: { type: "boolean", title: "Notify email", description: "Send an email after each scheduled run.", "x-order": 3, }, }, }, }, } as const; export const scheduleSchema = z .object({ cron: z.string().min(1).optional(), enabled: z.boolean().optional(), notifyEmail: z.boolean().optional(), }) .nullable() .optional(); export const configSchema = z.object({ platform: z.literal("hyperliquid").optional(), allocationMode: z.literal("target_notional").optional(), legAAsset: z.string().min(1).optional(), legBAsset: z.string().min(1).optional(), legAMarketType: z.enum(["spot", "perp"]).optional(), legBMarketType: z.enum(["spot", "perp"]).optional(), legASide: z.enum(["long", "short"]).optional(), longAsset: z.string().min(1).optional(), shortAsset: z.string().min(1).optional(), longMarketType: z.enum(["spot", "perp"]).optional(), shortMarketType: z.enum(["spot", "perp"]).optional(), targetNotionalUsd: z.number().positive().optional(), hedgeRatio: z.number().positive().optional(), legALeverage: z.number().positive().optional(), legBLeverage: z.number().positive().optional(), legALeverageMode: z.enum(["cross", "isolated"]).optional(), legBLeverageMode: z.enum(["cross", "isolated"]).optional(), slippageBps: z.number().int().min(0).max(5000).optional(), rebalanceDriftPct: z.number().positive().max(100).optional(), environment: z.enum(["mainnet", "testnet"]).optional(), schedule: scheduleSchema, });