mirror of
https://github.com/discountry/ritmex-bot.git
synced 2026-09-11 01:08:07 +00:00
feat: 添加基础网格策略支持,更新环境配置示例和文档,增强 CLI 和 UI 界面
This commit is contained in:
@@ -52,6 +52,15 @@ function parseNumber(value: string | undefined, fallback: number): number {
|
||||
return Number.isFinite(next) ? next : fallback;
|
||||
}
|
||||
|
||||
function parseBoolean(value: string | undefined, fallback: boolean): boolean {
|
||||
if (!value) return fallback;
|
||||
const normalized = value.trim().toLowerCase();
|
||||
if (!normalized) return fallback;
|
||||
if (normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on") return true;
|
||||
if (normalized === "0" || normalized === "false" || normalized === "no" || normalized === "off") return false;
|
||||
return fallback;
|
||||
}
|
||||
|
||||
export const tradingConfig: TradingConfig = {
|
||||
symbol: resolveSymbolFromEnv(),
|
||||
tradeAmount: parseNumber(process.env.TRADE_AMOUNT, 0.001),
|
||||
@@ -106,6 +115,26 @@ export interface BasisArbConfig {
|
||||
takerFeeRate: number;
|
||||
}
|
||||
|
||||
export type GridDirection = "both" | "long" | "short";
|
||||
|
||||
export interface GridConfig {
|
||||
symbol: string;
|
||||
lowerPrice: number;
|
||||
upperPrice: number;
|
||||
gridLevels: number;
|
||||
orderSize: number;
|
||||
maxPositionSize: number;
|
||||
refreshIntervalMs: number;
|
||||
maxLogEntries: number;
|
||||
priceTick: number;
|
||||
qtyStep: number;
|
||||
direction: GridDirection;
|
||||
stopLossPct: number;
|
||||
restartTriggerPct: number;
|
||||
autoRestart: boolean;
|
||||
gridMode: "geometric";
|
||||
}
|
||||
|
||||
const resolveBasisSymbol = (envKeys: string[], fallback: string): string => {
|
||||
for (const key of envKeys) {
|
||||
const value = process.env[key];
|
||||
@@ -130,6 +159,42 @@ export const basisConfig: BasisArbConfig = {
|
||||
takerFeeRate: parseNumber(process.env.BASIS_TAKER_FEE_RATE, 0.0004),
|
||||
};
|
||||
|
||||
const resolveGridDirection = (raw: string | undefined, fallback: GridDirection): GridDirection => {
|
||||
if (!raw) return fallback;
|
||||
const normalized = raw.trim().toLowerCase();
|
||||
if (normalized === "long" || normalized === "long-only") return "long";
|
||||
if (normalized === "short" || normalized === "short-only") return "short";
|
||||
if (normalized === "both" || normalized === "dual" || normalized === "bi" || normalized === "two-way") return "both";
|
||||
return fallback;
|
||||
};
|
||||
|
||||
const resolveGridMaxPosition = (orderSize: number, levels: number): number => {
|
||||
const fallback = Math.max(orderSize * Math.max(levels - 1, 1), orderSize);
|
||||
const raw = process.env.GRID_MAX_POSITION_SIZE ?? process.env.GRID_MAX_POSITION ?? process.env.GRID_POSITION_CAP;
|
||||
const parsed = parseNumber(raw, fallback);
|
||||
return parsed > 0 ? parsed : fallback;
|
||||
};
|
||||
|
||||
export const gridConfig: GridConfig = {
|
||||
symbol: resolveSymbolFromEnv(),
|
||||
lowerPrice: parseNumber(process.env.GRID_LOWER_PRICE ?? process.env.GRID_LOWER_BOUND, 0),
|
||||
upperPrice: parseNumber(process.env.GRID_UPPER_PRICE ?? process.env.GRID_UPPER_BOUND, 0),
|
||||
gridLevels: Math.max(2, Math.floor(parseNumber(process.env.GRID_LEVELS, 10))),
|
||||
orderSize: parseNumber(process.env.GRID_ORDER_SIZE, parseNumber(process.env.TRADE_AMOUNT, 0.001)),
|
||||
maxPositionSize: 0, // placeholder, replaced below
|
||||
refreshIntervalMs: parseNumber(process.env.GRID_REFRESH_INTERVAL_MS, 1_000),
|
||||
maxLogEntries: parseNumber(process.env.GRID_MAX_LOG_ENTRIES, 200),
|
||||
priceTick: parseNumber(process.env.GRID_PRICE_TICK ?? process.env.PRICE_TICK, 0.1),
|
||||
qtyStep: parseNumber(process.env.GRID_QTY_STEP ?? process.env.QTY_STEP, 0.001),
|
||||
direction: resolveGridDirection(process.env.GRID_DIRECTION, "both"),
|
||||
stopLossPct: Math.max(0, parseNumber(process.env.GRID_STOP_LOSS_PCT, 0.01)),
|
||||
restartTriggerPct: Math.max(0, parseNumber(process.env.GRID_RESTART_TRIGGER_PCT, 0.01)),
|
||||
autoRestart: parseBoolean(process.env.GRID_AUTO_RESTART_ENABLED ?? process.env.GRID_ENABLE_AUTO_RESTART, true),
|
||||
gridMode: "geometric",
|
||||
};
|
||||
|
||||
gridConfig.maxPositionSize = resolveGridMaxPosition(gridConfig.orderSize, gridConfig.gridLevels);
|
||||
|
||||
export function isBasisStrategyEnabled(): boolean {
|
||||
const raw = process.env.ENABLE_BASIS_STRATEGY;
|
||||
if (!raw) return false;
|
||||
|
||||
Reference in New Issue
Block a user