@extasyio/strategy-dsl
Version:
Declarative strategy builder and event bus for extasy-trading-core-libs
118 lines (112 loc) • 3.21 kB
JavaScript
;
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
});