UNPKG

@extasyio/strategy-dsl

Version:

Declarative strategy builder and event bus for extasy-trading-core-libs

118 lines (112 loc) 3.21 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var index_exports = {}; __export(index_exports, { EventBus: () => EventBus, StateMachine: () => StateMachine, StrategyBuilder: () => StrategyBuilder, and: () => and, not: () => not, or: () => or, withinHours: () => withinHours }); module.exports = __toCommonJS(index_exports); // src/event-bus.ts var EventBus = class { listeners = {}; on(event, handler) { (this.listeners[event] ||= []).push(handler); } emit(event, data) { this.listeners[event]?.forEach((h) => h(data)); } off(event, handler) { this.listeners[event] = (this.listeners[event] || []).filter((h) => h !== handler); } }; // src/fsm.ts var StateMachine = class { state = "idle"; get current() { return this.state; } enter(side) { if (this.state !== "idle") return; this.state = side; } exit() { if (this.state === "idle") return; this.state = "idle"; } toggle(side) { if (this.state === side) this.exit(); else this.enter(side); } reset() { this.state = "idle"; } }; // src/rules.ts var and = (...rules) => (v, s) => rules.every((r) => r(v, s)); var or = (...rules) => (v, s) => rules.some((r) => r(v, s)); var not = (rule) => (v, s) => !rule(v, s); var withinHours = (h) => ( // eslint-disable-next-line @typescript-eslint/no-unused-vars (_, __) => { const now = /* @__PURE__ */ new Date(); return now.getUTCHours() >= h[0] && now.getUTCHours() < h[1]; } ); // src/builder.ts var StrategyBuilder = class { constructor(opts) { this.opts = opts; } bus = new EventBus(); fsm = new StateMachine(); onSignal(cb) { this.bus.on("signal", cb); } feed(data, price, ts) { const val = this.opts.indicator.update(data); if (val === null) return; const sideToEnter = this.opts.enterRule(val); if (sideToEnter && this.fsm.current === "idle") { this.fsm.enter(sideToEnter); this.bus.emit("signal", { side: sideToEnter, price, ts }); return; } if (this.fsm.current !== "idle" && this.opts.exitRule(val, this.fsm.current)) { const exitSide = this.fsm.current === "long" ? "short" : "long"; this.fsm.exit(); this.bus.emit("signal", { side: exitSide, price, ts }); } } }; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { EventBus, StateMachine, StrategyBuilder, and, not, or, withinHours });