openpondai/agents/hyperliquid-delta-neutral
OpenTool app
typescript
import type { DeltaNeutralConfig } from "../config";
import { resolveDeltaScheduleMinutes } from "./schedule";
const HYPERLIQUID_PERP_VIP0_MAKER_FEE_RATE = 0.00015;
const HYPERLIQUID_PERP_VIP0_TAKER_FEE_RATE = 0.00045;
const HYPERLIQUID_SPOT_VIP0_MAKER_FEE_RATE = 0.0004;
const HYPERLIQUID_SPOT_VIP0_TAKER_FEE_RATE = 0.0007;
const HYPERLIQUID_BUILDER_FEE_RATE = 0.001;
export function resolveHyperliquidExchangeFeeRate(params: {
kind: "spot" | "perp";
feeModel?: "maker" | "taker";
}) {
const feeModel = params.feeModel ?? "taker";
if (params.kind === "perp") {
return feeModel === "maker"
? HYPERLIQUID_PERP_VIP0_MAKER_FEE_RATE
: HYPERLIQUID_PERP_VIP0_TAKER_FEE_RATE;
}
return feeModel === "maker"
? HYPERLIQUID_SPOT_VIP0_MAKER_FEE_RATE
: HYPERLIQUID_SPOT_VIP0_TAKER_FEE_RATE;
}
export function resolveHyperliquidBuilderFeeRate(params: {
kind: "spot" | "perp";
side: "buy" | "sell";
}) {
if (params.kind === "perp") {
return HYPERLIQUID_BUILDER_FEE_RATE;
}
return params.side === "sell" ? HYPERLIQUID_BUILDER_FEE_RATE : 0;
}
export function resolveHyperliquidTotalFeeRate(params: {
kind: "spot" | "perp";
side: "buy" | "sell";
feeModel?: "maker" | "taker";
}) {
const exchangeFeeRate = resolveHyperliquidExchangeFeeRate(params);
const builderFeeRate = resolveHyperliquidBuilderFeeRate(params);
return {
exchangeFeeRate,
builderFeeRate,
totalFeeRate: exchangeFeeRate + builderFeeRate,
};
}
export function estimateCarryEdgeUsd(params: {
config: DeltaNeutralConfig;
basisBps: number | null;
fundingRateBps: number | null;
hedgeNotionalUsd?: number;
}) {
const scheduleMinutes = resolveDeltaScheduleMinutes(params.config);
const spotTurnoverUsd = Math.max(0, params.config.targetNotionalUsd);
const hedgeNotionalUsd = Math.max(
0,
params.hedgeNotionalUsd ?? spotTurnoverUsd * Math.max(params.config.hedgeRatio ?? 1, 0),
);
const carryHours = Math.max(
Math.max(1, params.config.expectedCarryHours ?? 0),
(scheduleMinutes / 60) * 24,
);
const expectedFundingUsd =
params.fundingRateBps != null && params.fundingRateBps > 0
? hedgeNotionalUsd * (params.fundingRateBps / 10_000) * carryHours
: 0;
const expectedBasisCaptureUsd =
params.basisBps != null ? spotTurnoverUsd * (params.basisBps / 10_000) : 0;
const slippageRate = Math.max(0, params.config.slippageBps) / 10_000;
const estimatedPerpOpenCostUsd =
hedgeNotionalUsd *
(resolveHyperliquidTotalFeeRate({
kind: "perp",
side: "sell",
}).totalFeeRate + slippageRate);
const estimatedPerpCloseCostUsd =
hedgeNotionalUsd *
(resolveHyperliquidTotalFeeRate({
kind: "perp",
side: "buy",
}).totalFeeRate + slippageRate);
const estimatedOpenCostUsd = estimatedPerpOpenCostUsd;
const estimatedRoundTripCostUsd = estimatedPerpOpenCostUsd + estimatedPerpCloseCostUsd;
return {
carryHours,
expectedFundingUsd,
expectedBasisCaptureUsd,
estimatedOpenCostUsd,
estimatedRoundTripCostUsd,
netEdgeUsd:
expectedFundingUsd + expectedBasisCaptureUsd - estimatedRoundTripCostUsd,
};
}