openpondai/agents/signal-bot
OpenTool app
typescript
import {
fetchHyperliquidBars,
normalizeHyperliquidIndicatorBars,
} from "opentool/adapters/hyperliquid";
import {
DEFAULT_RSI_PRESET,
type SignalBotConfig,
} from "../config";
import { buildSignalIndicatorsOutput, resolveRsiThresholds } from "./indicator-output";
import { executePriceSignal } from "./execute-price-signal";
import { resolveTradeSignal } from "./trade-signal";
export async function runPriceSignalBot(config: SignalBotConfig) {
const rawBars = await fetchHyperliquidBars({
symbol: config.asset,
resolution: config.resolution,
countBack: config.countBack,
});
const bars = normalizeHyperliquidIndicatorBars(rawBars);
if (bars.length === 0) {
return {
ok: false,
error: "No price data returned.",
asset: config.asset,
signalType: config.signalType,
};
}
const closes = bars.map((bar) => bar.close);
const currentPrice = closes[closes.length - 1];
const asOf = new Date(bars[bars.length - 1]!.time).toISOString();
const output = buildSignalIndicatorsOutput(config, bars);
const { rsiPreset, overbought, oversold } = resolveRsiThresholds(config);
let execution: Record<string, unknown> | undefined;
let executionError: string | null = null;
if (config.execution?.enabled) {
const indicator = config.execution.indicator ?? config.indicators[0] ?? "rsi";
const tradeSignal = resolveTradeSignal(indicator, output);
({ execution, executionError } = await executePriceSignal({
config,
currentPrice,
tradeSignal,
indicator,
}));
}
if (executionError) {
return {
ok: false,
error: executionError,
asset: config.asset,
signalType: config.signalType,
resolution: config.resolution,
asOf,
price: currentPrice,
allocation: {
mode: config.allocationMode,
...(config.amountUsd ? { amountUsd: config.amountUsd } : {}),
},
indicators: output,
rsiPreset: rsiPreset ?? DEFAULT_RSI_PRESET,
rsiThresholds: { overbought, oversold },
...(execution ? { execution } : {}),
};
}
return {
ok: true,
asset: config.asset,
signalType: config.signalType,
resolution: config.resolution,
asOf,
price: currentPrice,
allocation: {
mode: config.allocationMode,
...(config.amountUsd ? { amountUsd: config.amountUsd } : {}),
},
indicators: output,
rsiPreset: rsiPreset ?? DEFAULT_RSI_PRESET,
rsiThresholds: { overbought, oversold },
...(execution ? { execution } : {}),
};
}