1Branch0Tags
GL
glucryptoRefresh package-lock for opentool 0.19.5
a06de7114 hours ago10Commits
typescript
import { z } from "zod"; import { buildHyperliquidProfileAssets } from "opentool/adapters/hyperliquid"; export type SimpleHyperliquidScheduleConfig = { cron: string; enabled: boolean; notifyEmail: boolean; }; export type SimpleHyperliquidExecutionConfig = { enabled: boolean; environment: "mainnet" | "testnet"; slippageBps: number; }; export type SimpleHyperliquidBacktestConfig = { configVersion?: number; platform: "hyperliquid"; asset: string; environment: "mainnet" | "testnet"; budgetUsd: number; twapDurationDays: number; monitoringPeriodHours: number; aggressiveSellThresholdPct: number; aggressiveMultiplier: number; resolution: "15" | "60" | "240" | "1D"; schedule?: SimpleHyperliquidScheduleConfig; execution?: SimpleHyperliquidExecutionConfig; }; const TEMPLATE_CONFIG_VERSION = 3; const TEMPLATE_CONFIG_ENV_VAR = "OPENTOOL_PUBLIC_HL_DIRECTIONAL_BOT_CONFIG"; const TEMPLATE_CONFIG_DEFAULTS: SimpleHyperliquidBacktestConfig = { configVersion: TEMPLATE_CONFIG_VERSION, platform: "hyperliquid", asset: "BTC", environment: "mainnet", budgetUsd: 1_000, twapDurationDays: 7, monitoringPeriodHours: 4, aggressiveSellThresholdPct: 2, aggressiveMultiplier: 1.5, resolution: "60", schedule: { cron: "0 * * * *", enabled: false, notifyEmail: false, }, execution: { enabled: false, environment: "mainnet", slippageBps: 30, }, }; const TEMPLATE_CONFIG_DEFAULT_SCHEDULE = TEMPLATE_CONFIG_DEFAULTS.schedule!; const TEMPLATE_CONFIG_DEFAULT_EXECUTION = TEMPLATE_CONFIG_DEFAULTS.execution!; const TEMPLATE_CONFIG_SCHEMA = { type: "object", required: [ "platform", "asset", "environment", "budgetUsd", "twapDurationDays", "monitoringPeriodHours", "aggressiveSellThresholdPct", "aggressiveMultiplier", "resolution", ], properties: { configVersion: { type: "number", title: "Config version", description: "Internal schema version for this TWAP starter.", readOnly: true, }, platform: { type: "string", enum: ["hyperliquid"], title: "Platform", description: "Execution venue for this starter.", readOnly: true, }, asset: { type: "string", title: "Asset", description: "Base asset to sell over time.", }, environment: { type: "string", enum: ["mainnet", "testnet"], title: "Environment", description: "Hyperliquid environment for reads and live execution.", }, budgetUsd: { type: "number", title: "Budget USD", description: "Total notional budget distributed across TWAP slices.", minimum: 1, }, twapDurationDays: { type: "number", title: "TWAP duration days", description: "How many days the sell program should span.", minimum: 1, maximum: 30, }, monitoringPeriodHours: { type: "number", title: "Monitoring period hours", description: "Hours between baseline TWAP slices and drop checks.", minimum: 1, maximum: 24, }, aggressiveSellThresholdPct: { type: "number", title: "Aggressive sell threshold %", description: "If price drops by at least this percent over one monitoring period, sell more aggressively.", minimum: 0.1, maximum: 25, }, aggressiveMultiplier: { type: "number", title: "Aggressive multiplier", description: "Multiplier applied to the baseline slice when the drop threshold is hit.", minimum: 1, maximum: 5, }, resolution: { type: "string", enum: ["15", "60", "240", "1D"], title: "Bar resolution", description: "Resolution used for preview backtests and live reads.", }, schedule: { type: "object", title: "Schedule", description: "Run cadence for scheduled checks.", properties: { cron: { type: "string", title: "Cron expression", description: "Cron string for scheduled runs.", }, enabled: { type: "boolean", title: "Enabled", description: "Enable the schedule.", }, notifyEmail: { type: "boolean", title: "Notify email", description: "Send an email after each scheduled execution.", }, }, }, execution: { type: "object", title: "Execution", description: "Optional live execution settings for real Hyperliquid orders.", properties: { enabled: { type: "boolean", title: "Enable live execution", description: "If enabled, live runs can place real Hyperliquid marketable orders.", }, environment: { type: "string", enum: ["mainnet", "testnet"], title: "Execution environment", description: "Hyperliquid environment used for live execution.", }, slippageBps: { type: "number", title: "Slippage basis points", description: "Marketable order slippage used for live execution.", minimum: 0, maximum: 500, }, }, }, }, }; export const DIRECTIONAL_BOT_TEMPLATE_CONFIG = { version: TEMPLATE_CONFIG_VERSION, schema: TEMPLATE_CONFIG_SCHEMA, defaults: TEMPLATE_CONFIG_DEFAULTS, envVar: TEMPLATE_CONFIG_ENV_VAR, }; const scheduleSchema = z .object({ cron: z.string().min(1).optional(), enabled: z.boolean().optional(), notifyEmail: z.boolean().optional(), }) .optional(); const executionSchema = z .object({ enabled: z.boolean().optional(), environment: z.enum(["mainnet", "testnet"]).optional(), slippageBps: z.number().min(0).max(500).optional(), }) .optional(); const configSchema = z.object({ platform: z.literal("hyperliquid").optional(), asset: z.string().min(1).optional(), environment: z.enum(["mainnet", "testnet"]).optional(), budgetUsd: z.number().positive().optional(), twapDurationDays: z.number().int().min(1).max(30).optional(), monitoringPeriodHours: z.number().int().min(1).max(24).optional(), aggressiveSellThresholdPct: z.number().positive().max(25).optional(), aggressiveMultiplier: z.number().min(1).max(5).optional(), resolution: z.enum(["15", "60", "240", "1D"]).optional(), schedule: scheduleSchema, execution: executionSchema, }); function normalizeConfig( config: SimpleHyperliquidBacktestConfig ): SimpleHyperliquidBacktestConfig { return { ...config, asset: config.asset.trim().toUpperCase() || TEMPLATE_CONFIG_DEFAULTS.asset, budgetUsd: Math.max(1, Number(config.budgetUsd)), twapDurationDays: Math.max(1, Math.round(config.twapDurationDays)), monitoringPeriodHours: Math.max(1, Math.round(config.monitoringPeriodHours)), aggressiveSellThresholdPct: Math.max( 0.1, Number(config.aggressiveSellThresholdPct) ), aggressiveMultiplier: Math.max(1, Number(config.aggressiveMultiplier)), }; } function mergeSchedule( schedule: Partial<SimpleHyperliquidScheduleConfig> | undefined ): SimpleHyperliquidScheduleConfig { return { cron: schedule?.cron ?? TEMPLATE_CONFIG_DEFAULT_SCHEDULE.cron, enabled: schedule?.enabled ?? TEMPLATE_CONFIG_DEFAULT_SCHEDULE.enabled, notifyEmail: schedule?.notifyEmail ?? TEMPLATE_CONFIG_DEFAULT_SCHEDULE.notifyEmail, }; } function mergeExecution( execution: Partial<SimpleHyperliquidExecutionConfig> | undefined ): SimpleHyperliquidExecutionConfig { return { enabled: execution?.enabled ?? TEMPLATE_CONFIG_DEFAULT_EXECUTION.enabled, environment: execution?.environment ?? TEMPLATE_CONFIG_DEFAULT_EXECUTION.environment, slippageBps: Math.max( 0, Math.min( 500, Number( execution?.slippageBps ?? TEMPLATE_CONFIG_DEFAULT_EXECUTION.slippageBps ) ) ), }; } export function readConfig(): SimpleHyperliquidBacktestConfig { const raw = process.env[TEMPLATE_CONFIG_ENV_VAR]; if (!raw) { return normalizeConfig(TEMPLATE_CONFIG_DEFAULTS); } try { const parsed = configSchema.parse(JSON.parse(raw)); return normalizeConfig({ ...TEMPLATE_CONFIG_DEFAULTS, ...parsed, schedule: mergeSchedule(parsed.schedule), execution: mergeExecution(parsed.execution), }); } catch { return normalizeConfig(TEMPLATE_CONFIG_DEFAULTS); } } export function resolveScheduleConfig(config: SimpleHyperliquidBacktestConfig) { const schedule = config.schedule ?? TEMPLATE_CONFIG_DEFAULT_SCHEDULE; if (!schedule?.cron) return undefined; return { cron: schedule.cron, enabled: schedule.enabled, notifyEmail: schedule.notifyEmail, }; } export function resolveProfileAssets(config: SimpleHyperliquidBacktestConfig) { return buildHyperliquidProfileAssets({ environment: config.environment, assets: [{ assetSymbols: [config.asset] }], }); }