mirror of
https://github.com/discountry/ritmex-bot.git
synced 2026-09-11 17:28:08 +00:00
更新 MakerEngine、OffsetMakerEngine 和 TrendEngine,优化账户、订单、深度、价格和K线推送的异常处理逻辑,确保在推送失败时记录错误信息以便于调试。
This commit is contained in:
+69
-18
@@ -109,7 +109,9 @@ export class MakerEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private bootstrap(): void {
|
private bootstrap(): void {
|
||||||
|
try {
|
||||||
this.exchange.watchAccount((snapshot) => {
|
this.exchange.watchAccount((snapshot) => {
|
||||||
|
try {
|
||||||
this.accountSnapshot = snapshot;
|
this.accountSnapshot = snapshot;
|
||||||
const totalUnrealized = Number(snapshot.totalUnrealizedProfit ?? "0");
|
const totalUnrealized = Number(snapshot.totalUnrealizedProfit ?? "0");
|
||||||
if (Number.isFinite(totalUnrealized)) {
|
if (Number.isFinite(totalUnrealized)) {
|
||||||
@@ -118,9 +120,17 @@ export class MakerEngine {
|
|||||||
const position = getPosition(snapshot, this.config.symbol);
|
const position = getPosition(snapshot, this.config.symbol);
|
||||||
this.updateSessionVolume(position);
|
this.updateSessionVolume(position);
|
||||||
this.emitUpdate();
|
this.emitUpdate();
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `账户推送处理异常: ${String(err)}`);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `订阅账户失败: ${String(err)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
this.exchange.watchOrders((orders) => {
|
this.exchange.watchOrders((orders) => {
|
||||||
|
try {
|
||||||
this.syncLocksWithOrders(orders);
|
this.syncLocksWithOrders(orders);
|
||||||
this.openOrders = Array.isArray(orders)
|
this.openOrders = Array.isArray(orders)
|
||||||
? orders.filter((order) => order.type !== "MARKET" && order.symbol === this.config.symbol)
|
? orders.filter((order) => order.type !== "MARKET" && order.symbol === this.config.symbol)
|
||||||
@@ -133,29 +143,60 @@ export class MakerEngine {
|
|||||||
}
|
}
|
||||||
this.initialOrderSnapshotReady = true;
|
this.initialOrderSnapshotReady = true;
|
||||||
this.emitUpdate();
|
this.emitUpdate();
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `订单推送处理异常: ${String(err)}`);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
} catch (err) {
|
||||||
this.exchange.watchDepth(this.config.symbol, (depth) => {
|
this.tradeLog.push("error", `订阅订单失败: ${String(err)}`);
|
||||||
this.depthSnapshot = depth;
|
|
||||||
this.emitUpdate();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.exchange.watchTicker(this.config.symbol, (ticker) => {
|
|
||||||
this.tickerSnapshot = ticker;
|
|
||||||
this.emitUpdate();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Maker strategy does not consume klines, but subscribe to keep parity with other modules
|
|
||||||
this.exchange.watchKlines(this.config.symbol, "1m", () => {
|
|
||||||
/* no-op */
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private syncLocksWithOrders(orders: AsterOrder[]): void {
|
try {
|
||||||
|
this.exchange.watchDepth(this.config.symbol, (depth) => {
|
||||||
|
try {
|
||||||
|
this.depthSnapshot = depth;
|
||||||
|
this.emitUpdate();
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `深度推送处理异常: ${String(err)}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `订阅深度失败: ${String(err)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.exchange.watchTicker(this.config.symbol, (ticker) => {
|
||||||
|
try {
|
||||||
|
this.tickerSnapshot = ticker;
|
||||||
|
this.emitUpdate();
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `价格推送处理异常: ${String(err)}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `订阅Ticker失败: ${String(err)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maker strategy does not consume klines, but subscribe to keep parity with other modules
|
||||||
|
try {
|
||||||
|
this.exchange.watchKlines(this.config.symbol, "1m", () => {
|
||||||
|
try {
|
||||||
|
/* no-op */
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `K线推送处理异常: ${String(err)}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `订阅K线失败: ${String(err)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private syncLocksWithOrders(orders: AsterOrder[] | null | undefined): void {
|
||||||
|
const list = Array.isArray(orders) ? orders : [];
|
||||||
Object.keys(this.pending).forEach((type) => {
|
Object.keys(this.pending).forEach((type) => {
|
||||||
const pendingId = this.pending[type];
|
const pendingId = this.pending[type];
|
||||||
if (!pendingId) return;
|
if (!pendingId) return;
|
||||||
const match = orders.find((order) => String(order.orderId) === pendingId);
|
const match = list.find((order) => String(order.orderId) === pendingId);
|
||||||
if (!match || (match.status && match.status !== "NEW" && match.status !== "PARTIALLY_FILLED")) {
|
if (!match || (match.status && match.status !== "NEW" && match.status !== "PARTIALLY_FILLED")) {
|
||||||
unlockOperating(this.locks, this.timers, this.pending, type);
|
unlockOperating(this.locks, this.timers, this.pending, type);
|
||||||
}
|
}
|
||||||
@@ -407,10 +448,20 @@ export class MakerEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private emitUpdate(): void {
|
private emitUpdate(): void {
|
||||||
|
try {
|
||||||
const snapshot = this.buildSnapshot();
|
const snapshot = this.buildSnapshot();
|
||||||
const handlers = this.listeners.get("update");
|
const handlers = this.listeners.get("update");
|
||||||
if (handlers) {
|
if (handlers) {
|
||||||
handlers.forEach((handler) => handler(snapshot));
|
handlers.forEach((handler) => {
|
||||||
|
try {
|
||||||
|
handler(snapshot);
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `更新回调处理异常: ${String(err)}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `快照或更新分发异常: ${String(err)}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -108,7 +108,9 @@ export class OffsetMakerEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private bootstrap(): void {
|
private bootstrap(): void {
|
||||||
|
try {
|
||||||
this.exchange.watchAccount((snapshot) => {
|
this.exchange.watchAccount((snapshot) => {
|
||||||
|
try {
|
||||||
this.accountSnapshot = snapshot;
|
this.accountSnapshot = snapshot;
|
||||||
const totalUnrealized = Number(snapshot.totalUnrealizedProfit ?? "0");
|
const totalUnrealized = Number(snapshot.totalUnrealizedProfit ?? "0");
|
||||||
if (Number.isFinite(totalUnrealized)) {
|
if (Number.isFinite(totalUnrealized)) {
|
||||||
@@ -117,9 +119,17 @@ export class OffsetMakerEngine {
|
|||||||
const position = getPosition(snapshot, this.config.symbol);
|
const position = getPosition(snapshot, this.config.symbol);
|
||||||
this.updateSessionVolume(position);
|
this.updateSessionVolume(position);
|
||||||
this.emitUpdate();
|
this.emitUpdate();
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `账户推送处理异常: ${String(err)}`);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `订阅账户失败: ${String(err)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
this.exchange.watchOrders((orders) => {
|
this.exchange.watchOrders((orders) => {
|
||||||
|
try {
|
||||||
this.syncLocksWithOrders(orders);
|
this.syncLocksWithOrders(orders);
|
||||||
this.openOrders = Array.isArray(orders)
|
this.openOrders = Array.isArray(orders)
|
||||||
? orders.filter((order) => order.type !== "MARKET" && order.symbol === this.config.symbol)
|
? orders.filter((order) => order.type !== "MARKET" && order.symbol === this.config.symbol)
|
||||||
@@ -132,28 +142,59 @@ export class OffsetMakerEngine {
|
|||||||
}
|
}
|
||||||
this.initialOrderSnapshotReady = true;
|
this.initialOrderSnapshotReady = true;
|
||||||
this.emitUpdate();
|
this.emitUpdate();
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `订单推送处理异常: ${String(err)}`);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
} catch (err) {
|
||||||
this.exchange.watchDepth(this.config.symbol, (depth) => {
|
this.tradeLog.push("error", `订阅订单失败: ${String(err)}`);
|
||||||
this.depthSnapshot = depth;
|
|
||||||
this.emitUpdate();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.exchange.watchTicker(this.config.symbol, (ticker) => {
|
|
||||||
this.tickerSnapshot = ticker;
|
|
||||||
this.emitUpdate();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.exchange.watchKlines(this.config.symbol, "1m", () => {
|
|
||||||
/* no-op */
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private syncLocksWithOrders(orders: AsterOrder[]): void {
|
try {
|
||||||
|
this.exchange.watchDepth(this.config.symbol, (depth) => {
|
||||||
|
try {
|
||||||
|
this.depthSnapshot = depth;
|
||||||
|
this.emitUpdate();
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `深度推送处理异常: ${String(err)}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `订阅深度失败: ${String(err)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.exchange.watchTicker(this.config.symbol, (ticker) => {
|
||||||
|
try {
|
||||||
|
this.tickerSnapshot = ticker;
|
||||||
|
this.emitUpdate();
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `价格推送处理异常: ${String(err)}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `订阅Ticker失败: ${String(err)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.exchange.watchKlines(this.config.symbol, "1m", () => {
|
||||||
|
try {
|
||||||
|
/* no-op */
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `K线推送处理异常: ${String(err)}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `订阅K线失败: ${String(err)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private syncLocksWithOrders(orders: AsterOrder[] | null | undefined): void {
|
||||||
|
const list = Array.isArray(orders) ? orders : [];
|
||||||
Object.keys(this.pending).forEach((type) => {
|
Object.keys(this.pending).forEach((type) => {
|
||||||
const pendingId = this.pending[type];
|
const pendingId = this.pending[type];
|
||||||
if (!pendingId) return;
|
if (!pendingId) return;
|
||||||
const match = orders.find((order) => String(order.orderId) === pendingId);
|
const match = list.find((order) => String(order.orderId) === pendingId);
|
||||||
if (!match || (match.status && match.status !== "NEW" && match.status !== "PARTIALLY_FILLED")) {
|
if (!match || (match.status && match.status !== "NEW" && match.status !== "PARTIALLY_FILLED")) {
|
||||||
unlockOperating(this.locks, this.timers, this.pending, type);
|
unlockOperating(this.locks, this.timers, this.pending, type);
|
||||||
}
|
}
|
||||||
@@ -499,10 +540,20 @@ export class OffsetMakerEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private emitUpdate(): void {
|
private emitUpdate(): void {
|
||||||
|
try {
|
||||||
const snapshot = this.buildSnapshot();
|
const snapshot = this.buildSnapshot();
|
||||||
const handlers = this.listeners.get("update");
|
const handlers = this.listeners.get("update");
|
||||||
if (handlers) {
|
if (handlers) {
|
||||||
handlers.forEach((handler) => handler(snapshot));
|
handlers.forEach((handler) => {
|
||||||
|
try {
|
||||||
|
handler(snapshot);
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `更新回调处理异常: ${String(err)}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `快照或更新分发异常: ${String(err)}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -126,13 +126,23 @@ export class TrendEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private bootstrap(): void {
|
private bootstrap(): void {
|
||||||
|
try {
|
||||||
this.exchange.watchAccount((snapshot) => {
|
this.exchange.watchAccount((snapshot) => {
|
||||||
|
try {
|
||||||
this.accountSnapshot = snapshot;
|
this.accountSnapshot = snapshot;
|
||||||
const position = getPosition(snapshot, this.config.symbol);
|
const position = getPosition(snapshot, this.config.symbol);
|
||||||
this.updateSessionVolume(position);
|
this.updateSessionVolume(position);
|
||||||
this.emitUpdate();
|
this.emitUpdate();
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `账户推送处理异常: ${String(err)}`);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `订阅账户失败: ${String(err)}`);
|
||||||
|
}
|
||||||
|
try {
|
||||||
this.exchange.watchOrders((orders) => {
|
this.exchange.watchOrders((orders) => {
|
||||||
|
try {
|
||||||
this.synchronizeLocks(orders);
|
this.synchronizeLocks(orders);
|
||||||
this.openOrders = Array.isArray(orders)
|
this.openOrders = Array.isArray(orders)
|
||||||
? orders.filter((order) => order.type !== "MARKET" && order.symbol === this.config.symbol)
|
? orders.filter((order) => order.type !== "MARKET" && order.symbol === this.config.symbol)
|
||||||
@@ -148,26 +158,57 @@ export class TrendEngine {
|
|||||||
}
|
}
|
||||||
this.ordersSnapshotReady = true;
|
this.ordersSnapshotReady = true;
|
||||||
this.emitUpdate();
|
this.emitUpdate();
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `订单推送处理异常: ${String(err)}`);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `订阅订单失败: ${String(err)}`);
|
||||||
|
}
|
||||||
|
try {
|
||||||
this.exchange.watchDepth(this.config.symbol, (depth) => {
|
this.exchange.watchDepth(this.config.symbol, (depth) => {
|
||||||
|
try {
|
||||||
this.depthSnapshot = depth;
|
this.depthSnapshot = depth;
|
||||||
this.emitUpdate();
|
this.emitUpdate();
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `深度推送处理异常: ${String(err)}`);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `订阅深度失败: ${String(err)}`);
|
||||||
|
}
|
||||||
|
try {
|
||||||
this.exchange.watchTicker(this.config.symbol, (ticker) => {
|
this.exchange.watchTicker(this.config.symbol, (ticker) => {
|
||||||
|
try {
|
||||||
this.tickerSnapshot = ticker;
|
this.tickerSnapshot = ticker;
|
||||||
this.emitUpdate();
|
this.emitUpdate();
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `价格推送处理异常: ${String(err)}`);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `订阅Ticker失败: ${String(err)}`);
|
||||||
|
}
|
||||||
|
try {
|
||||||
this.exchange.watchKlines(this.config.symbol, this.config.klineInterval, (klines) => {
|
this.exchange.watchKlines(this.config.symbol, this.config.klineInterval, (klines) => {
|
||||||
this.klineSnapshot = klines;
|
try {
|
||||||
|
this.klineSnapshot = Array.isArray(klines) ? klines : [];
|
||||||
this.emitUpdate();
|
this.emitUpdate();
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `K线推送处理异常: ${String(err)}`);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `订阅K线失败: ${String(err)}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronizeLocks(orders: AsterOrder[]): void {
|
private synchronizeLocks(orders: AsterOrder[] | null | undefined): void {
|
||||||
|
const list = Array.isArray(orders) ? orders : [];
|
||||||
Object.keys(this.pending).forEach((type) => {
|
Object.keys(this.pending).forEach((type) => {
|
||||||
const pendingId = this.pending[type];
|
const pendingId = this.pending[type];
|
||||||
if (!pendingId) return;
|
if (!pendingId) return;
|
||||||
const match = orders.find((order) => String(order.orderId) === pendingId);
|
const match = list.find((order) => String(order.orderId) === pendingId);
|
||||||
if (!match || (match.status && match.status !== "NEW")) {
|
if (!match || (match.status && match.status !== "NEW")) {
|
||||||
unlockOperating(this.locks, this.timers, this.pending, type);
|
unlockOperating(this.locks, this.timers, this.pending, type);
|
||||||
}
|
}
|
||||||
@@ -532,10 +573,20 @@ export class TrendEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private emitUpdate(): void {
|
private emitUpdate(): void {
|
||||||
|
try {
|
||||||
const snapshot = this.buildSnapshot();
|
const snapshot = this.buildSnapshot();
|
||||||
const handlers = this.listeners.get("update");
|
const handlers = this.listeners.get("update");
|
||||||
if (handlers) {
|
if (handlers) {
|
||||||
handlers.forEach((handler) => handler(snapshot));
|
handlers.forEach((handler) => {
|
||||||
|
try {
|
||||||
|
handler(snapshot);
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `更新回调处理异常: ${String(err)}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
this.tradeLog.push("error", `快照或更新分发异常: ${String(err)}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user