@vulcan-js/strategies 0.0.2 → 0.1.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @vulcan-js/strategies
2
2
 
3
- Composable trading strategies for the [Vulcan](../../README.md) library. Combines multiple indicators into structured signal output with position management.
3
+ Composable trading strategies for the [Vulcan](https://github.com/material-tech/vulcan) library. Combines multiple indicators into structured signal output with position management.
4
4
 
5
5
  ## Installation
6
6
 
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
- import { assert } from "@vulcan-js/core";
1
+ import { assert, toDnum } from "@vulcan-js/core";
2
2
  import { defu } from "defu";
3
3
  import { rsi, sma } from "@vulcan-js/indicators";
4
- import { from, gt, lt, toNumber } from "dnum";
4
+ import { gt, lt, toNumber } from "dnum";
5
5
 
6
6
  //#region src/base.ts
7
7
  /**
@@ -92,7 +92,7 @@ const goldenCross = createStrategy(({ fastPeriod, slowPeriod, stopLossPercent })
92
92
  return (ctx) => {
93
93
  const close = ctx.bar.c;
94
94
  const fastAbove = gt(fastSma(close), slowSma(close));
95
- const price = toNumber(from(close, 18));
95
+ const price = toNumber(toDnum(close));
96
96
  let signal = { action: "hold" };
97
97
  if (prevFastAbove !== void 0) {
98
98
  if (fastAbove && !prevFastAbove) signal = {
@@ -131,8 +131,8 @@ const defaultRsiOversoldOverboughtOptions = {
131
131
  const rsiOversoldOverbought = createStrategy(({ period, overboughtLevel, oversoldLevel }) => {
132
132
  const rsiProc = rsi.create({ period });
133
133
  let prevRsi;
134
- const obLevel = from(overboughtLevel, 18);
135
- const osLevel = from(oversoldLevel, 18);
134
+ const obLevel = toDnum(overboughtLevel);
135
+ const osLevel = toDnum(oversoldLevel);
136
136
  return (ctx) => {
137
137
  const close = ctx.bar.c;
138
138
  const currentRsi = rsiProc(close);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/base.ts","../src/builtin/goldenCross.ts","../src/builtin/rsiOversoldOverbought.ts"],"sourcesContent":["import type { BaseStrategyOptions, CandleData, Processor, StrategyContext, StrategyFactory, StrategyGenerator, StrategySignal } from './types'\nimport { assert } from '@vulcan-js/core'\nimport { defu } from 'defu'\n\n/**\n * A fixed-capacity ring buffer with O(1) push and O(n) snapshot.\n */\nfunction createRingBuffer<T>(capacity: number) {\n const buf: T[] = Array.from({ length: capacity })\n let head = 0\n let size = 0\n\n return {\n push(item: T) {\n buf[head] = item\n head = (head + 1) % capacity\n if (size < capacity)\n size++\n },\n toArray(): readonly T[] {\n if (size < capacity) {\n return buf.slice(0, size)\n }\n // head points to the oldest element when buffer is full\n return [...buf.slice(head), ...buf.slice(0, head)]\n },\n get size() {\n return size\n },\n }\n}\n\n/**\n * Create a generator-based strategy from a strategy factory.\n *\n * Mirrors `createSignal` from core, but manages a rolling window of bars\n * and constructs a `StrategyContext` for each evaluation.\n *\n * The returned generator is fully compatible with `SignalGenerator<CandleData, StrategySignal, Opts>`.\n */\nexport function createStrategy<Opts extends BaseStrategyOptions>(\n factory: StrategyFactory<Opts>,\n defaultOptions: Opts,\n): StrategyGenerator<Opts> {\n function buildProcessor(options?: Partial<Opts>): Processor<CandleData, StrategySignal> {\n const opt = defu(options, defaultOptions) as Required<Opts>\n assert(Number.isInteger(opt.windowSize) && opt.windowSize >= 1, new RangeError(`Expected windowSize to be a positive integer, got ${opt.windowSize}`))\n const ring = createRingBuffer<CandleData>(opt.windowSize)\n const process = factory(opt)\n let index = 0\n return (bar: CandleData) => {\n ring.push(bar)\n const ctx: StrategyContext = { bar, bars: ring.toArray(), index }\n const signal = process(ctx)\n index++\n return signal\n }\n }\n\n function* generator(\n source: Iterable<CandleData>,\n options?: Partial<Opts>,\n ): Generator<StrategySignal, void, unknown> {\n const process = buildProcessor(options)\n for (const bar of source) {\n yield process(bar)\n }\n }\n\n generator.create = (options?: Partial<Opts>): Processor<CandleData, StrategySignal> => {\n return buildProcessor(options)\n }\n\n Object.defineProperty(generator, 'defaultOptions', {\n get() {\n return JSON.parse(JSON.stringify(defaultOptions))\n },\n })\n\n return generator as StrategyGenerator<Opts>\n}\n","import type { Dnum, Numberish } from 'dnum'\nimport type { BaseStrategyOptions, StrategySignal } from '../types'\nimport { sma } from '@vulcan-js/indicators'\nimport { from, gt, toNumber } from 'dnum'\nimport { createStrategy } from '../base'\n\nexport interface GoldenCrossOptions extends BaseStrategyOptions {\n /** Fast SMA period */\n fastPeriod: number\n /** Slow SMA period */\n slowPeriod: number\n /** Stop-loss percentage (0–1), e.g. 0.02 = 2% */\n stopLossPercent: number\n}\n\nexport const defaultGoldenCrossOptions: GoldenCrossOptions = {\n windowSize: 2,\n fastPeriod: 50,\n slowPeriod: 200,\n stopLossPercent: 0.02,\n}\n\n/**\n * Golden Cross / Death Cross Strategy\n *\n * Detects when a fast SMA crosses above (golden cross → long) or\n * below (death cross → short) a slow SMA.\n *\n * - **Golden Cross**: fast SMA crosses above slow SMA → `long`\n * - **Death Cross**: fast SMA crosses below slow SMA → `short`\n * - Otherwise → `hold`\n *\n * Stop-loss is set as a percentage below/above the entry price.\n */\nexport const goldenCross = createStrategy(\n ({ fastPeriod, slowPeriod, stopLossPercent }) => {\n const fastSma = sma.create({ period: fastPeriod })\n const slowSma = sma.create({ period: slowPeriod })\n let prevFastAbove: boolean | undefined\n\n return (ctx) => {\n const close = ctx.bar.c as Numberish\n const fast: Dnum = fastSma(close)\n const slow: Dnum = slowSma(close)\n const fastAbove = gt(fast, slow)\n const price = toNumber(from(close, 18))\n\n let signal: StrategySignal = { action: 'hold' }\n\n if (prevFastAbove !== undefined) {\n if (fastAbove && !prevFastAbove) {\n signal = {\n action: 'long',\n stopLoss: price * (1 - stopLossPercent),\n reason: 'Golden cross: fast SMA crossed above slow SMA',\n }\n }\n else if (!fastAbove && prevFastAbove) {\n signal = {\n action: 'short',\n stopLoss: price * (1 + stopLossPercent),\n reason: 'Death cross: fast SMA crossed below slow SMA',\n }\n }\n }\n\n prevFastAbove = fastAbove\n\n return signal\n }\n },\n defaultGoldenCrossOptions,\n)\n\nexport { goldenCross as goldenCrossStrategy }\n","import type { Dnum, Numberish } from 'dnum'\nimport type { BaseStrategyOptions, StrategySignal } from '../types'\nimport { rsi } from '@vulcan-js/indicators'\nimport { from, gt, lt } from 'dnum'\nimport { createStrategy } from '../base'\n\nexport interface RsiOversoldOverboughtOptions extends BaseStrategyOptions {\n /** RSI calculation period */\n period: number\n /** RSI level above which the asset is considered overbought */\n overboughtLevel: number\n /** RSI level below which the asset is considered oversold */\n oversoldLevel: number\n}\n\nexport const defaultRsiOversoldOverboughtOptions: RsiOversoldOverboughtOptions = {\n windowSize: 2,\n period: 14,\n overboughtLevel: 70,\n oversoldLevel: 30,\n}\n\n/**\n * RSI Oversold/Overbought Strategy\n *\n * Uses the Relative Strength Index to detect oversold and overbought conditions.\n *\n * - RSI crosses below `oversoldLevel` then back above → `long` (oversold reversal)\n * - RSI crosses above `overboughtLevel` then back below → `short` (overbought reversal)\n * - Otherwise → `hold`\n */\nexport const rsiOversoldOverbought = createStrategy(\n ({ period, overboughtLevel, oversoldLevel }) => {\n const rsiProc = rsi.create({ period })\n let prevRsi: Dnum | undefined\n const obLevel = from(overboughtLevel, 18)\n const osLevel = from(oversoldLevel, 18)\n\n return (ctx) => {\n const close = ctx.bar.c as Numberish\n const currentRsi = rsiProc(close)\n\n let signal: StrategySignal = { action: 'hold' }\n\n if (prevRsi !== undefined) {\n // Oversold reversal: RSI was below oversoldLevel, now crosses above\n if (lt(prevRsi, osLevel) && gt(currentRsi, osLevel)) {\n signal = {\n action: 'long',\n reason: `RSI crossed above oversold level (${oversoldLevel})`,\n }\n }\n // Overbought reversal: RSI was above overboughtLevel, now crosses below\n else if (gt(prevRsi, obLevel) && lt(currentRsi, obLevel)) {\n signal = {\n action: 'short',\n reason: `RSI crossed below overbought level (${overboughtLevel})`,\n }\n }\n }\n\n prevRsi = currentRsi\n\n return signal\n }\n },\n defaultRsiOversoldOverboughtOptions,\n)\n\nexport { rsiOversoldOverbought as rsiOversoldOverboughtStrategy }\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/base.ts","../src/builtin/goldenCross.ts","../src/builtin/rsiOversoldOverbought.ts"],"sourcesContent":["import type { BaseStrategyOptions, CandleData, Processor, StrategyContext, StrategyFactory, StrategyGenerator, StrategySignal } from './types'\nimport { assert } from '@vulcan-js/core'\nimport { defu } from 'defu'\n\n/**\n * A fixed-capacity ring buffer with O(1) push and O(n) snapshot.\n */\nfunction createRingBuffer<T>(capacity: number) {\n const buf: T[] = Array.from({ length: capacity })\n let head = 0\n let size = 0\n\n return {\n push(item: T) {\n buf[head] = item\n head = (head + 1) % capacity\n if (size < capacity)\n size++\n },\n toArray(): readonly T[] {\n if (size < capacity) {\n return buf.slice(0, size)\n }\n // head points to the oldest element when buffer is full\n return [...buf.slice(head), ...buf.slice(0, head)]\n },\n get size() {\n return size\n },\n }\n}\n\n/**\n * Create a generator-based strategy from a strategy factory.\n *\n * Mirrors `createSignal` from core, but manages a rolling window of bars\n * and constructs a `StrategyContext` for each evaluation.\n *\n * The returned generator is fully compatible with `SignalGenerator<CandleData, StrategySignal, Opts>`.\n */\nexport function createStrategy<Opts extends BaseStrategyOptions>(\n factory: StrategyFactory<Opts>,\n defaultOptions: Opts,\n): StrategyGenerator<Opts> {\n function buildProcessor(options?: Partial<Opts>): Processor<CandleData, StrategySignal> {\n const opt = defu(options, defaultOptions) as Required<Opts>\n assert(Number.isInteger(opt.windowSize) && opt.windowSize >= 1, new RangeError(`Expected windowSize to be a positive integer, got ${opt.windowSize}`))\n const ring = createRingBuffer<CandleData>(opt.windowSize)\n const process = factory(opt)\n let index = 0\n return (bar: CandleData) => {\n ring.push(bar)\n const ctx: StrategyContext = { bar, bars: ring.toArray(), index }\n const signal = process(ctx)\n index++\n return signal\n }\n }\n\n function* generator(\n source: Iterable<CandleData>,\n options?: Partial<Opts>,\n ): Generator<StrategySignal, void, unknown> {\n const process = buildProcessor(options)\n for (const bar of source) {\n yield process(bar)\n }\n }\n\n generator.create = (options?: Partial<Opts>): Processor<CandleData, StrategySignal> => {\n return buildProcessor(options)\n }\n\n Object.defineProperty(generator, 'defaultOptions', {\n get() {\n return JSON.parse(JSON.stringify(defaultOptions))\n },\n })\n\n return generator as StrategyGenerator<Opts>\n}\n","import type { Dnum, Numberish } from 'dnum'\nimport type { BaseStrategyOptions, StrategySignal } from '../types'\nimport { toDnum } from '@vulcan-js/core'\nimport { sma } from '@vulcan-js/indicators'\nimport { gt, toNumber } from 'dnum'\nimport { createStrategy } from '../base'\n\nexport interface GoldenCrossOptions extends BaseStrategyOptions {\n /** Fast SMA period */\n fastPeriod: number\n /** Slow SMA period */\n slowPeriod: number\n /** Stop-loss percentage (0–1), e.g. 0.02 = 2% */\n stopLossPercent: number\n}\n\nexport const defaultGoldenCrossOptions: GoldenCrossOptions = {\n windowSize: 2,\n fastPeriod: 50,\n slowPeriod: 200,\n stopLossPercent: 0.02,\n}\n\n/**\n * Golden Cross / Death Cross Strategy\n *\n * Detects when a fast SMA crosses above (golden cross → long) or\n * below (death cross → short) a slow SMA.\n *\n * - **Golden Cross**: fast SMA crosses above slow SMA → `long`\n * - **Death Cross**: fast SMA crosses below slow SMA → `short`\n * - Otherwise → `hold`\n *\n * Stop-loss is set as a percentage below/above the entry price.\n */\nexport const goldenCross = createStrategy(\n ({ fastPeriod, slowPeriod, stopLossPercent }) => {\n const fastSma = sma.create({ period: fastPeriod })\n const slowSma = sma.create({ period: slowPeriod })\n let prevFastAbove: boolean | undefined\n\n return (ctx) => {\n const close = ctx.bar.c as Numberish\n const fast: Dnum = fastSma(close)\n const slow: Dnum = slowSma(close)\n const fastAbove = gt(fast, slow)\n const price = toNumber(toDnum(close))\n\n let signal: StrategySignal = { action: 'hold' }\n\n if (prevFastAbove !== undefined) {\n if (fastAbove && !prevFastAbove) {\n signal = {\n action: 'long',\n stopLoss: price * (1 - stopLossPercent),\n reason: 'Golden cross: fast SMA crossed above slow SMA',\n }\n }\n else if (!fastAbove && prevFastAbove) {\n signal = {\n action: 'short',\n stopLoss: price * (1 + stopLossPercent),\n reason: 'Death cross: fast SMA crossed below slow SMA',\n }\n }\n }\n\n prevFastAbove = fastAbove\n\n return signal\n }\n },\n defaultGoldenCrossOptions,\n)\n\nexport { goldenCross as goldenCrossStrategy }\n","import type { Dnum, Numberish } from 'dnum'\nimport type { BaseStrategyOptions, StrategySignal } from '../types'\nimport { toDnum } from '@vulcan-js/core'\nimport { rsi } from '@vulcan-js/indicators'\nimport { gt, lt } from 'dnum'\nimport { createStrategy } from '../base'\n\nexport interface RsiOversoldOverboughtOptions extends BaseStrategyOptions {\n /** RSI calculation period */\n period: number\n /** RSI level above which the asset is considered overbought */\n overboughtLevel: number\n /** RSI level below which the asset is considered oversold */\n oversoldLevel: number\n}\n\nexport const defaultRsiOversoldOverboughtOptions: RsiOversoldOverboughtOptions = {\n windowSize: 2,\n period: 14,\n overboughtLevel: 70,\n oversoldLevel: 30,\n}\n\n/**\n * RSI Oversold/Overbought Strategy\n *\n * Uses the Relative Strength Index to detect oversold and overbought conditions.\n *\n * - RSI crosses below `oversoldLevel` then back above → `long` (oversold reversal)\n * - RSI crosses above `overboughtLevel` then back below → `short` (overbought reversal)\n * - Otherwise → `hold`\n */\nexport const rsiOversoldOverbought = createStrategy(\n ({ period, overboughtLevel, oversoldLevel }) => {\n const rsiProc = rsi.create({ period })\n let prevRsi: Dnum | undefined\n const obLevel = toDnum(overboughtLevel)\n const osLevel = toDnum(oversoldLevel)\n\n return (ctx) => {\n const close = ctx.bar.c as Numberish\n const currentRsi = rsiProc(close)\n\n let signal: StrategySignal = { action: 'hold' }\n\n if (prevRsi !== undefined) {\n // Oversold reversal: RSI was below oversoldLevel, now crosses above\n if (lt(prevRsi, osLevel) && gt(currentRsi, osLevel)) {\n signal = {\n action: 'long',\n reason: `RSI crossed above oversold level (${oversoldLevel})`,\n }\n }\n // Overbought reversal: RSI was above overboughtLevel, now crosses below\n else if (gt(prevRsi, obLevel) && lt(currentRsi, obLevel)) {\n signal = {\n action: 'short',\n reason: `RSI crossed below overbought level (${overboughtLevel})`,\n }\n }\n }\n\n prevRsi = currentRsi\n\n return signal\n }\n },\n defaultRsiOversoldOverboughtOptions,\n)\n\nexport { rsiOversoldOverbought as rsiOversoldOverboughtStrategy }\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vulcan-js/strategies",
3
3
  "type": "module",
4
- "version": "0.0.2",
4
+ "version": "0.1.0-beta.2",
5
5
  "description": "Composable trading strategies with structured signal output for the Vulcan library",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -27,15 +27,14 @@
27
27
  "dependencies": {
28
28
  "defu": "^6.1.4",
29
29
  "dnum": "^2.17.0",
30
- "@vulcan-js/core": "^0.0.2",
31
- "@vulcan-js/indicators": "^0.0.2"
30
+ "@vulcan-js/core": "^0.1.0-beta.2",
31
+ "@vulcan-js/indicators": "^0.1.0-beta.2"
32
32
  },
33
33
  "devDependencies": {
34
34
  "vite-tsconfig-paths": "^6.1.1",
35
35
  "vitest": "^4.0.18"
36
36
  },
37
37
  "scripts": {
38
- "build": "tsdown",
39
38
  "test": "vitest run"
40
39
  }
41
40
  }