openpondai/agents/hyperliquid-delta-neutral
OpenTool app
typescript
import {
resolveHyperliquidMaxPerRunUsd,
} from "opentool/adapters/hyperliquid";
import {
TEMPLATE_CONFIG_DEFAULTS,
TEMPLATE_CONFIG_ENV_VAR,
TEMPLATE_CONFIG_VERSION,
} from "./defaults";
import { configSchema, TEMPLATE_CONFIG_SCHEMA } from "./schema";
import type { DeltaNeutralConfig } from "./types";
export const DELTA_NEUTRAL_TEMPLATE_CONFIG = {
version: TEMPLATE_CONFIG_VERSION,
schema: TEMPLATE_CONFIG_SCHEMA,
defaults: TEMPLATE_CONFIG_DEFAULTS,
envVar: TEMPLATE_CONFIG_ENV_VAR,
};
export function readConfig(): DeltaNeutralConfig {
const defaultSchedule = TEMPLATE_CONFIG_DEFAULTS.schedule ?? {
cron: "0 * * * *",
enabled: false,
notifyEmail: false,
};
const raw = process.env[TEMPLATE_CONFIG_ENV_VAR];
if (!raw) {
const targetNotionalUsd = TEMPLATE_CONFIG_DEFAULTS.targetNotionalUsd;
const hedgeRatio = TEMPLATE_CONFIG_DEFAULTS.hedgeRatio;
const maxPerRunUsd = resolveHyperliquidMaxPerRunUsd(targetNotionalUsd, hedgeRatio);
const deltaDriftUsd =
(targetNotionalUsd * TEMPLATE_CONFIG_DEFAULTS.deltaDriftPct) / 100;
return {
...TEMPLATE_CONFIG_DEFAULTS,
maxPerRunUsd,
deltaDriftUsd,
};
}
try {
const parsed = configSchema.parse(JSON.parse(raw));
const merged = {
...TEMPLATE_CONFIG_DEFAULTS,
...parsed,
spotAsset: parsed.spotAsset ?? TEMPLATE_CONFIG_DEFAULTS.spotAsset,
perpAsset: parsed.perpAsset ?? TEMPLATE_CONFIG_DEFAULTS.perpAsset,
schedule: {
cron: parsed.schedule?.cron ?? defaultSchedule.cron,
enabled: parsed.schedule?.enabled ?? defaultSchedule.enabled,
notifyEmail: parsed.schedule?.notifyEmail ?? defaultSchedule.notifyEmail,
},
};
const targetNotionalUsd = Number.isFinite(merged.targetNotionalUsd)
? merged.targetNotionalUsd
: TEMPLATE_CONFIG_DEFAULTS.targetNotionalUsd;
const hedgeRatio = Number.isFinite(merged.hedgeRatio)
? merged.hedgeRatio
: TEMPLATE_CONFIG_DEFAULTS.hedgeRatio;
const deltaDriftPct = Number.isFinite(merged.deltaDriftPct)
? merged.deltaDriftPct
: TEMPLATE_CONFIG_DEFAULTS.deltaDriftPct;
const computedDeltaDriftUsd =
(targetNotionalUsd * deltaDriftPct) / 100;
return {
...merged,
allocationMode: "target_notional",
spotAsset: merged.spotAsset,
perpAsset: merged.perpAsset,
deltaDriftPct,
maxPerRunUsd: resolveHyperliquidMaxPerRunUsd(targetNotionalUsd, hedgeRatio),
deltaDriftUsd: computedDeltaDriftUsd,
};
} catch {
const targetNotionalUsd = TEMPLATE_CONFIG_DEFAULTS.targetNotionalUsd;
const hedgeRatio = TEMPLATE_CONFIG_DEFAULTS.hedgeRatio;
const maxPerRunUsd = resolveHyperliquidMaxPerRunUsd(targetNotionalUsd, hedgeRatio);
const deltaDriftUsd =
(targetNotionalUsd * TEMPLATE_CONFIG_DEFAULTS.deltaDriftPct) / 100;
return {
...TEMPLATE_CONFIG_DEFAULTS,
maxPerRunUsd,
deltaDriftUsd,
};
}
}
export function resolveScheduleConfig(config: DeltaNeutralConfig) {
const schedule = config.schedule ?? TEMPLATE_CONFIG_DEFAULTS.schedule;
if (!schedule || !schedule.cron) return undefined;
return {
cron: schedule.cron,
enabled: schedule.enabled,
notifyEmail: schedule.notifyEmail,
};
}
export function resolveProfileAssets(config: DeltaNeutralConfig) {
const assetSymbols = Array.from(
new Set(
[config.spotAsset, config.perpAsset]
.map((value) => value.trim())
.filter((value) => value.length > 0),
),
);
if (assetSymbols.length === 0) {
return [];
}
return [
{
venue: "hyperliquid" as const,
chain:
config.environment === "testnet"
? ("hyperliquid-testnet" as const)
: ("hyperliquid" as const),
assetSymbols,
},
];
}