import React, { useMemo, useState } from "react"; import { Box, Text, useInput } from "ink"; import { TrendApp } from "./TrendApp"; import { MakerApp } from "./MakerApp"; import { OffsetMakerApp } from "./OffsetMakerApp"; import { loadCopyrightFragments, verifyCopyrightIntegrity } from "../utils/copyright"; import { resolveExchangeId } from "../exchanges/create-adapter"; interface StrategyOption { id: "trend" | "maker" | "offset-maker"; label: string; description: string; component: React.ComponentType<{ onExit: () => void }>; } const STRATEGIES: StrategyOption[] = [ { id: "trend", label: "趋势跟随策略 (SMA30)", description: "监控均线信号,自动进出场并维护止损/止盈", component: TrendApp, }, { id: "maker", label: "做市刷单策略", description: "双边挂单提供流动性,自动追价与风控止损", component: MakerApp, }, { id: "offset-maker", label: "偏移做市策略", description: "根据盘口深度自动偏移挂单并在极端不平衡时撤退", component: OffsetMakerApp, }, ]; const inputSupported = Boolean(process.stdin && (process.stdin as any).isTTY); export function App() { const [cursor, setCursor] = useState(0); const [selected, setSelected] = useState(null); const copyright = useMemo(() => loadCopyrightFragments(), []); const integrityOk = useMemo(() => verifyCopyrightIntegrity(), []); const exchangeId = useMemo(() => resolveExchangeId(), []); const strategies = useMemo(() => STRATEGIES, []); useInput( (input, key) => { if (selected) return; if (key.upArrow) { setCursor((prev) => (prev - 1 + strategies.length) % strategies.length); } else if (key.downArrow) { setCursor((prev) => (prev + 1) % strategies.length); } else if (key.return) { const strategy = strategies[cursor]; if (strategy) { setSelected(strategy); } } }, { isActive: inputSupported && !selected } ); if (selected) { const Selected = selected.component; return setSelected(null)} />; } return ( {copyright.bannerText} {integrityOk ? null : ( 警告: 版权校验失败,当前版本可能被篡改。 )} ──────────────────────────────────────────────────── 请选择要运行的策略 使用 ↑/↓ 选择,回车开始,Ctrl+C 退出。 {strategies.map((strategy, index) => { const active = index === cursor; return ( {active ? "➤" : " "} {strategy.label} {strategy.description} ); })} ); }