feat: 引入事件发射器和会话交易量跟踪器,重构策略引擎以支持更灵活的事件处理和交易量计算

This commit is contained in:
discountry
2025-09-28 00:43:49 +08:00
parent 25ab1ababf
commit 6ab0759d3d
6 changed files with 357 additions and 351 deletions
+30
View File
@@ -0,0 +1,30 @@
export class StrategyEventEmitter<TEvent extends string, TPayload> {
private readonly listeners = new Map<TEvent, Set<(payload: TPayload) => void>>();
on(event: TEvent, handler: (payload: TPayload) => void): void {
const handlers = this.listeners.get(event) ?? new Set<(payload: TPayload) => void>();
handlers.add(handler);
this.listeners.set(event, handlers);
}
off(event: TEvent, handler: (payload: TPayload) => void): void {
const handlers = this.listeners.get(event);
if (!handlers) return;
handlers.delete(handler);
if (handlers.size === 0) {
this.listeners.delete(event);
}
}
emit(event: TEvent, payload: TPayload, onError?: (error: unknown) => void): void {
const handlers = this.listeners.get(event);
if (!handlers) return;
for (const handler of handlers) {
try {
handler(payload);
} catch (error) {
onError?.(error);
}
}
}
}
+28
View File
@@ -0,0 +1,28 @@
import type { PositionSnapshot } from "../../utils/strategy";
export class SessionVolumeTracker {
private initialized = false;
private previousPositionAmt = 0;
private total = 0;
update(position: PositionSnapshot, referencePrice: number | null): void {
if (!this.initialized) {
this.previousPositionAmt = position.positionAmt;
this.initialized = true;
return;
}
if (referencePrice == null) {
this.previousPositionAmt = position.positionAmt;
return;
}
const delta = Math.abs(position.positionAmt - this.previousPositionAmt);
if (delta > 0) {
this.total += delta * referencePrice;
}
this.previousPositionAmt = position.positionAmt;
}
get value(): number {
return this.total;
}
}
+25
View File
@@ -0,0 +1,25 @@
export type LogHandler = (type: string, detail: string) => void;
interface SubscriptionMessages {
subscribeFail: (error: unknown) => string;
processFail: (error: unknown) => string;
}
export function safeSubscribe<T>(
subscribe: (cb: (payload: T) => void) => void,
handler: (payload: T) => void,
log: LogHandler,
messages: SubscriptionMessages
): void {
try {
subscribe((payload) => {
try {
handler(payload);
} catch (error) {
log("error", messages.processFail(error));
}
});
} catch (error) {
log("error", messages.subscribeFail(error));
}
}