1Branch0Tags
GL
glucryptoFix exact Hyperliquid symbols
typescript
import { z } from "zod"; import { LIMITS } from "./defaults"; export const indicatorSchema = z.enum([ "rsi", "macd", "bb", "sma", "ema", "ma-cross", "donchian", ]); export const TEMPLATE_CONFIG_SCHEMA = { type: "object", "x-budget": { modeField: "allocationMode", defaultMode: "fixed", title: "Budget & allocation", description: "Directional signal starters use fixed USD sizing.", modes: { fixed: { fields: ["indicators", "amountUsd"], }, }, }, properties: { configVersion: { type: "number", title: "Config version", description: "Internal version for signal-bot defaults.", readOnly: true, "x-hidden": true, "x-section": "Meta", "x-order": 1000, }, platform: { type: "string", enum: ["hyperliquid"], title: "Platform", description: "Execution venue for this strategy.", readOnly: true, "x-hidden": true, "x-section": "Meta", "x-order": 1001, }, signalType: { type: "string", enum: ["price"], title: "Strategy type", description: "Internal strategy identifier.", "x-enumLabels": ["Price"], readOnly: true, "x-hidden": true, "x-section": "Meta", "x-order": 1002, }, asset: { type: "string", title: "Asset", description: "Default Hyperliquid perp symbol. Use execution symbol for spot pairs (BASE-QUOTE or BASE/QUOTE) or HIP-3 symbols (dex:BASE).", "x-format": "asset", "x-section": "Strategy", "x-order": 1, }, indicators: { type: "array", title: "Indicators", description: "Indicators to evaluate for price-based signals.", items: { type: "string", enum: ["rsi", "macd", "bb", "sma", "ema", "ma-cross", "donchian"], "x-enumLabels": [ "RSI", "MACD", "Bollinger Bands", "SMA", "EMA", "MA Cross", "Donchian", ], }, "x-section": "Strategy", "x-order": 2, }, allocationMode: { type: "string", enum: ["fixed"], title: "Allocation mode", description: "Position sizing method.", "x-enumLabels": ["Fixed USD"], readOnly: true, "x-hidden": true, "x-section": "Risk", "x-order": 1, }, amountUsd: { type: "number", title: "Fixed amount", description: "USD notional per run when allocation mode is fixed.", minimum: 1, "x-unit": "USD", "x-format": "currency", "x-step": 1, "x-section": "Risk", "x-order": 2, }, schedule: { type: "object", title: "Schedule", description: "Run toggles and notifications.", "x-section": "Schedule", properties: { cron: { type: "string", title: "Cron expression", description: "Cron expression for automated runs.", "x-order": 1, }, enabled: { type: "boolean", title: "Enabled", description: "Enable scheduled runs.", "x-order": 2, }, notifyEmail: { type: "boolean", title: "Notify email", description: "Send an email after scheduled runs.", "x-order": 3, }, }, }, resolution: { type: "string", enum: ["1", "5", "15", "30", "60", "240", "1D", "1W"], title: "Resolution", description: "Bar timeframe for price data.", "x-section": "Price model", "x-order": 1, }, countBack: { type: "number", title: "Bars to fetch", description: "Number of historical bars for indicator calculations.", minimum: 50, maximum: 5000, "x-step": 1, "x-section": "Price model", "x-order": 2, }, price: { type: "object", title: "Price settings", description: "Indicator-specific tuning.", "x-section": "Price model", properties: { rsiPreset: { type: "string", title: "RSI preset", description: "Preset thresholds for RSI.", "x-visibleIf": { field: "indicators", contains: "rsi" }, "x-order": 10, }, rsi: { type: "object", title: "RSI thresholds", description: "Custom RSI overbought/oversold values.", properties: { overbought: { type: "number", title: "RSI overbought", description: "Overbought threshold.", minimum: 1, maximum: 100, "x-visibleIf": { field: "indicators", contains: "rsi" }, "x-order": 11, }, oversold: { type: "number", title: "RSI oversold", description: "Oversold threshold.", minimum: 1, maximum: 100, "x-visibleIf": { field: "indicators", contains: "rsi" }, "x-order": 12, }, }, }, movingAverage: { type: "object", title: "Moving average", description: "Configuration for SMA/EMA checks.", properties: { type: { type: "string", enum: ["sma", "ema"], title: "Average type", description: "Moving average type.", "x-visibleIf": { field: "indicators", containsAny: ["sma", "ema"] }, "x-order": 20, }, period: { type: "number", title: "Average period", description: "Lookback period for moving average.", minimum: 2, maximum: 240, "x-step": 1, "x-visibleIf": { field: "indicators", containsAny: ["sma", "ema"] }, "x-order": 21, }, }, }, maCross: { type: "object", title: "MA cross", description: "Fast/slow moving average cross settings.", properties: { type: { type: "string", enum: ["sma", "ema"], title: "Cross type", description: "Moving average type used in cross logic.", "x-visibleIf": { field: "indicators", contains: "ma-cross" }, "x-order": 30, }, fastPeriod: { type: "number", title: "Fast period", description: "Fast moving average lookback.", minimum: 2, maximum: 239, "x-step": 1, "x-visibleIf": { field: "indicators", contains: "ma-cross" }, "x-order": 31, }, slowPeriod: { type: "number", title: "Slow period", description: "Slow moving average lookback.", minimum: 3, maximum: 240, "x-step": 1, "x-visibleIf": { field: "indicators", contains: "ma-cross" }, "x-order": 32, }, }, }, bollinger: { type: "object", title: "Bollinger bands", description: "Period and standard deviation settings.", properties: { period: { type: "number", title: "BB period", description: "Lookback period for Bollinger bands.", minimum: 5, maximum: 240, "x-step": 1, "x-visibleIf": { field: "indicators", contains: "bb" }, "x-order": 40, }, stdDev: { type: "number", title: "BB std dev", description: "Standard deviation multiplier.", minimum: 0.5, maximum: 5, "x-step": 0.1, "x-visibleIf": { field: "indicators", contains: "bb" }, "x-order": 41, }, }, }, donchian: { type: "object", title: "Donchian", description: "Breakout channel lookback settings.", properties: { period: { type: "number", title: "Donchian period", description: "Bars used to build the channel.", minimum: 2, maximum: 240, "x-step": 1, "x-visibleIf": { field: "indicators", contains: "donchian" }, "x-order": 60, }, }, }, }, }, execution: { type: "object", title: "Execution", description: "Live trading controls and routing.", "x-section": "Execution", properties: { enabled: { type: "boolean", title: "Execution enabled", description: "Submit live orders when signals trigger.", "x-order": 1, }, environment: { type: "string", enum: ["testnet", "mainnet"], title: "Environment", description: "Execution environment for Hyperliquid.", "x-enumLabels": ["Testnet", "Mainnet"], "x-order": 2, }, symbol: { type: "string", title: "Execution symbol", description: "Optional exact Hyperliquid symbol override. Use BASE-QUOTE or BASE/QUOTE for spot, bare BASE for perps, or dex:BASE for HIP-3.", "x-order": 3, }, mode: { type: "string", enum: ["long-only", "long-short"], title: "Execution mode", description: "Allow long-only or long-short positioning.", "x-enumLabels": ["Long only", "Long + short"], "x-order": 4, }, size: { type: "number", title: "Explicit size", description: "Optional explicit position size override.", minimum: 0, "x-step": 0.0001, "x-order": 5, }, indicator: { type: "string", enum: ["rsi", "macd", "bb", "sma", "ema", "ma-cross", "donchian"], title: "Execution indicator", description: "Indicator used to decide trade direction.", "x-order": 6, }, leverage: { type: "number", title: "Leverage", description: "Target leverage for perpetual execution.", minimum: 1, maximum: 50, "x-unit": "x", "x-step": 1, "x-order": 7, }, slippageBps: { type: "number", title: "Execution slippage", description: "Max slippage for signal-driven orders.", minimum: 0, maximum: 500, "x-unit": "bps", "x-format": "bps", "x-step": 1, "x-order": 8, }, }, }, }, } as const; export const configSchema = z .object({ platform: z.literal("hyperliquid").optional(), asset: z.string().min(1).optional(), signalType: z.literal("price").optional(), indicators: z.array(indicatorSchema).optional(), allocationMode: z.literal("fixed").optional(), amountUsd: z.number().positive().optional(), schedule: z .object({ cron: z.string().min(1).optional(), enabled: z.boolean().optional(), notifyEmail: z.boolean().optional(), }) .optional(), resolution: z.enum(["1", "5", "15", "30", "60", "240", "1D", "1W"]).optional(), countBack: z.number().int().min(50).max(5000).optional(), price: z .object({ rsiPreset: z.string().optional(), rsi: z .object({ overbought: z.number().optional(), oversold: z.number().optional(), }) .optional(), movingAverage: z .object({ type: z.enum(["sma", "ema"]).optional(), period: z .number() .int() .min(LIMITS.movingAverage.min) .max(LIMITS.movingAverage.max) .optional(), }) .optional(), maCross: z .object({ type: z.enum(["sma", "ema"]).optional(), fastPeriod: z .number() .int() .min(LIMITS.maCross.fastMin) .max(LIMITS.maCross.fastMax) .optional(), slowPeriod: z .number() .int() .min(LIMITS.maCross.slowMin) .max(LIMITS.maCross.slowMax) .optional(), }) .optional(), bollinger: z .object({ period: z .number() .int() .min(LIMITS.bollinger.periodMin) .max(LIMITS.bollinger.periodMax) .optional(), stdDev: z .number() .min(LIMITS.bollinger.stdDevMin) .max(LIMITS.bollinger.stdDevMax) .optional(), }) .optional(), donchian: z .object({ period: z .number() .int() .min(LIMITS.donchian.min) .max(LIMITS.donchian.max) .optional(), }) .optional(), }) .optional(), execution: z .object({ enabled: z.boolean().optional(), environment: z.enum(["testnet", "mainnet"]).optional(), symbol: z.string().optional(), mode: z.enum(["long-only", "long-short"]).optional(), size: z.number().positive().optional(), leverage: z.number().positive().optional(), slippageBps: z.number().min(0).max(500).optional(), indicator: indicatorSchema.optional(), }) .optional(), }) .partial();