@alphacharts/drawings 0.0.0-stage → 0.1.1

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.
@@ -0,0 +1,32 @@
1
+ import type { Anchor, ToolDef } from "../types.js";
2
+ export declare function xabcdRatios(x: Anchor, a: Anchor, b: Anchor, c: Anchor, d: Anchor): {
3
+ abXa: number | null;
4
+ bcAb: number | null;
5
+ cdBc: number | null;
6
+ adXa: number | null;
7
+ };
8
+ export declare function cypherRatios(x: Anchor, a: Anchor, b: Anchor, c: Anchor, d: Anchor): {
9
+ abXa: number | null;
10
+ xcXa: number | null;
11
+ cdXc: number | null;
12
+ };
13
+ export declare function abcdRatios(a: Anchor, b: Anchor, c: Anchor, d: Anchor): {
14
+ bcAb: number | null;
15
+ cdBc: number | null;
16
+ };
17
+ export declare function driveRatios(pts: readonly Anchor[]): (number | null)[];
18
+ export declare const xabcd: ToolDef;
19
+ export declare const cypher: ToolDef;
20
+ export declare const abcd: ToolDef;
21
+ export declare const trianglePattern: ToolDef;
22
+ export declare const threeDrives: ToolDef;
23
+ export declare const headAndShoulders: ToolDef;
24
+ export type Degree = "minuette" | "minor" | "intermediate" | "primary";
25
+ /** Wave label for a degree: minuette ((1)), minor 1, intermediate (1), primary [1]. */
26
+ export declare function waveLabel(degree: Degree, n: string): string;
27
+ export declare const elliottImpulse: ToolDef;
28
+ export declare const elliottCorrection: ToolDef;
29
+ export declare const elliottTriangle: ToolDef;
30
+ export declare const elliottDoubleCombo: ToolDef;
31
+ export declare const elliottTripleCombo: ToolDef;
32
+ export declare const patternTools: ToolDef[];
@@ -0,0 +1,55 @@
1
+ import type { Bar } from "../source.js";
2
+ import type { Anchor, Drawing, ToolDef } from "../types.js";
3
+ export type Side = "long" | "short";
4
+ export interface PositionInputs {
5
+ accountSize?: number | null;
6
+ /** Percent of the account risked between entry and stop. */
7
+ riskPercent?: number | undefined;
8
+ lotSize?: number | undefined;
9
+ }
10
+ export interface PositionStats {
11
+ /** Price distance entry→stop and entry→target (both ≥ 0). */
12
+ risk: number;
13
+ reward: number;
14
+ /** reward / risk, or null when risk is 0. */
15
+ rr: number | null;
16
+ riskPct: number;
17
+ rewardPct: number;
18
+ /** Units to trade so that a stop-out loses at most accountSize·riskPercent/100; null without an account size or with 0 risk. */
19
+ qty: number | null;
20
+ /** qty × reward and qty × risk. */
21
+ profit: number | null;
22
+ loss: number | null;
23
+ }
24
+ export declare function positionStats(side: Side, entry: number, target: number, stop: number, o?: PositionInputs): PositionStats;
25
+ export declare function statsOf(side: Side, d: Drawing): PositionStats;
26
+ export declare const longPosition: ToolDef;
27
+ export declare const shortPosition: ToolDef;
28
+ export declare const forecast: ToolDef;
29
+ /** The end of the projected move: same Δprice as a0→a1, started at a2. */
30
+ export declare function projectionTarget(a0: Anchor, a1: Anchor, a2: Anchor): number;
31
+ export declare const projection: ToolDef;
32
+ /** Bars of [lo, hi) shifted so that the first bar's close sits at `price`; times keep their offsets from the first bar. */
33
+ export declare function patternBars(bars: readonly Bar[], price: number): Array<{
34
+ offsetMs: number;
35
+ open: number;
36
+ high: number;
37
+ low: number;
38
+ close: number;
39
+ }>;
40
+ export declare const barsPattern: ToolDef;
41
+ /** mulberry32: a small seeded PRNG so a ghost feed redraws identically. */
42
+ export declare function seeded(seed: number): () => number;
43
+ /**
44
+ * `count` synthetic bars: each is a randomly drawn bar of `history` with its
45
+ * open-relative high/low/close added to the previous synthetic close,
46
+ * starting from `start`. Deterministic for a seed.
47
+ */
48
+ export declare function ghostBars(history: readonly Bar[], start: number, count: number, seed: number): Array<{
49
+ open: number;
50
+ high: number;
51
+ low: number;
52
+ close: number;
53
+ }>;
54
+ export declare const ghostFeed: ToolDef;
55
+ export declare const positionTools: ToolDef[];
@@ -0,0 +1,64 @@
1
+ import type { Pt } from "../geometry.js";
2
+ import type { BarSource } from "../source.js";
3
+ import type { Anchor, Drawing, DrawingStyle, Shape, Stroke, ToolCtx, ToolDef } from "../types.js";
4
+ /** Anchor i of a drawing; a missing one is a bug in the caller, not a default. */
5
+ export declare function A(d: Drawing, i: number): Anchor;
6
+ export declare const px: (c: ToolCtx, a: Anchor) => Pt;
7
+ export declare const pxs: (c: ToolCtx, d: Drawing) => Pt[];
8
+ export declare function prop<T>(d: Drawing, key: string): T;
9
+ export declare function numProp(d: Drawing, key: string): number;
10
+ export declare function levelsProp(d: Drawing): number[];
11
+ export declare function line(a: Pt, b: Pt, o?: Stroke & {
12
+ extA?: boolean;
13
+ extB?: boolean;
14
+ }): Shape;
15
+ export declare function poly(pts: readonly Pt[], o?: Stroke & {
16
+ close?: boolean;
17
+ fill?: string | null;
18
+ }): Shape;
19
+ /** A filled polygon with no outline and no hit-test (bands, shading). */
20
+ export declare function shade(pts: readonly Pt[], fill: string): Shape;
21
+ export declare function text(x: number, y: number, t: string, o?: Omit<Extract<Shape, {
22
+ k: "text";
23
+ }>, "k" | "x" | "y" | "text">): Shape;
24
+ /** Filled arrow head at b for a shaft from a (hit-test off: the shaft carries the hit). */
25
+ export declare function head(a: Pt, b: Pt, size: number, color: string): Shape;
26
+ /** extendLeft/extendRight are in time terms: map them to the ends of the segment a→b (a may be the later one). */
27
+ export declare function extension(style: DrawingStyle, a: Pt, b: Pt): {
28
+ extA: boolean;
29
+ extB: boolean;
30
+ };
31
+ export declare const lerp: (a: Pt, b: Pt, t: number) => Pt;
32
+ export declare const mid: (a: Pt, b: Pt) => Pt;
33
+ export declare function fillOf(style: DrawingStyle, alpha?: number): string;
34
+ export declare function fmtTime(t: number): string;
35
+ /** Whole days/hours/minutes (seconds under a minute) of a duration in ms. */
36
+ export declare function fmtDuration(ms: number): string;
37
+ export interface Measure {
38
+ dPrice: number;
39
+ /** Δ/|from|·100, or null when the start price is 0. */
40
+ pct: number | null;
41
+ /** Bars from a0 to a1 (fractional between bars), or null without a bar source. */
42
+ bars: number | null;
43
+ dTime: number;
44
+ }
45
+ export declare function measure(a0: Anchor, a1: Anchor, source: BarSource | null): Measure;
46
+ export declare function barsText(bars: number): string;
47
+ /** "+12.50 (+0.05%)", then "34 bars, 2h 5m" when known. */
48
+ export declare function measureLines(m: Measure, c: ToolCtx): string[];
49
+ /** Ratio b/a of two price moves, or null when a is 0. */
50
+ export declare function ratio(num: number, den: number): number | null;
51
+ export declare function ratioText(r: number | null): string;
52
+ export declare const FIB_COLORS: Record<string, string>;
53
+ export declare const fibColor: (r: number) => string;
54
+ export declare const FIB_RETRACEMENT: number[];
55
+ export declare const FIB_BASIC: number[];
56
+ /** Tool factory: fills the optional members so definitions stay short. */
57
+ export declare function tool(t: ToolDef): ToolDef;
58
+ export declare const lineDefaults: (style?: Partial<DrawingStyle>, props?: Record<string, unknown>) => () => {
59
+ style: Partial<DrawingStyle>;
60
+ props: Record<string, unknown>;
61
+ };
62
+ export declare function needDistinctTimes(d: Drawing, i: number, j: number): void;
63
+ /** Validate every anchor is finite. */
64
+ export declare function finiteAnchors(d: Drawing): void;
@@ -0,0 +1,31 @@
1
+ import type { BarSource } from "../source.js";
2
+ import type { ToolDef } from "../types.js";
3
+ export interface VwapSeries {
4
+ times: Float64Array;
5
+ values: Float64Array;
6
+ }
7
+ /**
8
+ * VWAP from bar `start` to the last bar: Σ(typical·volume) / Σ(volume), typical
9
+ * = (high + low + close) / 3. Bars before the first with volume have no value (NaN).
10
+ */
11
+ export declare function anchoredVwap(src: BarSource, start: number): VwapSeries;
12
+ /** Index of the bar the anchor sits on: the last bar at or before its time (the first bar if it is earlier than all). */
13
+ export declare function startIndex(src: BarSource, time: number): number | null;
14
+ export declare const anchoredVwapTool: ToolDef;
15
+ export interface VolumeProfile {
16
+ low: number;
17
+ high: number;
18
+ rowHeight: number;
19
+ volumes: number[];
20
+ poc: number;
21
+ }
22
+ /**
23
+ * Bar-level volume profile of bars [lo, hi): a bar's volume is spread over
24
+ * the rows its [low, high] range overlaps, in proportion to the overlap
25
+ * (all of it in one row when low = high). This approximates real traded-at-
26
+ * price volume, which a bar series does not contain. The row volumes sum to
27
+ * the bars' total volume.
28
+ */
29
+ export declare function volumeProfile(src: BarSource, lo: number, hi: number, rows: number): VolumeProfile;
30
+ export declare const volumeProfileTool: ToolDef;
31
+ export declare const volumeTools: ToolDef[];
@@ -0,0 +1,156 @@
1
+ import type { BarSource } from "./source.js";
2
+ export interface Anchor {
3
+ /** UTC ms. Not required to be a bar time: it may sit between bars or past the last bar. */
4
+ time: number;
5
+ price: number;
6
+ }
7
+ export type Dash = "solid" | "dashed" | "dotted";
8
+ export interface DrawingStyle {
9
+ color: string;
10
+ /** CSS px. */
11
+ width: number;
12
+ dash: Dash;
13
+ /** CSS colour with alpha, or null for no fill. */
14
+ fill: string | null;
15
+ textColor: string;
16
+ /** CSS px. */
17
+ fontSize: number;
18
+ bold: boolean;
19
+ italic: boolean;
20
+ text: string;
21
+ extendLeft: boolean;
22
+ extendRight: boolean;
23
+ }
24
+ export interface Drawing {
25
+ id: string;
26
+ tool: string;
27
+ pane: number;
28
+ anchors: Anchor[];
29
+ style: DrawingStyle;
30
+ /** Tool-specific, JSON-safe (levels, account size, seeds …). */
31
+ props: Record<string, unknown>;
32
+ locked: boolean;
33
+ hidden: boolean;
34
+ /** Chart intervals (bar length in ms) the drawing shows on; null = all. */
35
+ intervals: number[] | null;
36
+ }
37
+ export interface Stroke {
38
+ color?: string;
39
+ width?: number;
40
+ dash?: Dash;
41
+ /** false: drawn but not hit-testable (decorations, fills). Default true. */
42
+ hit?: boolean;
43
+ }
44
+ export type Shape = (Stroke & {
45
+ k: "line";
46
+ x1: number;
47
+ y1: number;
48
+ x2: number;
49
+ y2: number;
50
+ extA?: boolean;
51
+ extB?: boolean;
52
+ }) | (Stroke & {
53
+ k: "poly";
54
+ pts: number[];
55
+ close?: boolean;
56
+ fill?: string | null;
57
+ round?: boolean;
58
+ }) | (Stroke & {
59
+ k: "ellipse";
60
+ cx: number;
61
+ cy: number;
62
+ rx: number;
63
+ ry: number;
64
+ rot?: number;
65
+ fill?: string | null;
66
+ }) | (Stroke & {
67
+ k: "arc";
68
+ cx: number;
69
+ cy: number;
70
+ r: number;
71
+ a0: number;
72
+ a1: number;
73
+ fill?: string | null;
74
+ }) | (Stroke & {
75
+ k: "text";
76
+ x: number;
77
+ y: number;
78
+ text: string;
79
+ align?: "left" | "center" | "right";
80
+ base?: "top" | "middle" | "bottom";
81
+ /** Text colour (default: the drawing's text colour). */
82
+ textColor?: string;
83
+ size?: number;
84
+ bg?: string | null;
85
+ /** Border of the background box. */
86
+ border?: string | null;
87
+ pad?: number;
88
+ /**
89
+ * A label that gives way: when the pane draws it over another stacking label it is moved down just clear of it
90
+ * (the price labels of several levels close in price do not print over one another).
91
+ */
92
+ stack?: boolean;
93
+ });
94
+ export interface ToolCtx {
95
+ /** Pane size in CSS px. */
96
+ readonly W: number;
97
+ readonly H: number;
98
+ readonly dpr: number;
99
+ X(time: number): number;
100
+ Y(price: number): number;
101
+ T(x: number): number;
102
+ P(y: number): number;
103
+ /** The series' price formatter. */
104
+ fmt(price: number): string;
105
+ /** Bars of the main series, for tools that read them (and bar counts). */
106
+ readonly source: BarSource | null;
107
+ /** Current chart interval in ms, if known. */
108
+ readonly interval: number | null;
109
+ }
110
+ export type Gesture =
111
+ /** Press, drag, release: anchors 0 and 1 (a click then a click works too). Further anchors by click. */
112
+ "drag"
113
+ /** One click per anchor. */
114
+ | "clicks"
115
+ /** One click. */
116
+ | "single"
117
+ /** Press-drag-release collecting points. */
118
+ | "freehand";
119
+ export interface ToolDef {
120
+ readonly id: string;
121
+ readonly label: string;
122
+ readonly family: string;
123
+ readonly gesture: Gesture;
124
+ /** Anchors (the minimum for variable tools). 0 for screen-anchored tools. */
125
+ readonly anchors: number;
126
+ /** Any number of anchors ≥ `anchors`: finish with double-click or Enter. */
127
+ readonly variable?: boolean;
128
+ /** Positioned by props.fx / props.fy (fractions of the pane), not by time and price. */
129
+ readonly screen?: boolean;
130
+ /** Reads bars: the plugin must have a BarSource. */
131
+ readonly needsSource?: boolean;
132
+ /** No handles (brush strokes: moving the whole stroke only). */
133
+ readonly noHandles?: boolean;
134
+ defaults(): {
135
+ style?: Partial<DrawingStyle>;
136
+ props?: Record<string, unknown>;
137
+ };
138
+ shapes(d: Drawing, c: ToolCtx): Shape[];
139
+ /** Throw (with context) when anchors or props are not valid for the tool. */
140
+ validate?(d: Drawing): void;
141
+ /** Called after anchor `i` was set by an edit; enforce invariants. */
142
+ constrain?(d: Drawing, i: number): void;
143
+ /** Fill props that depend on the view when the drawing is created (may throw). */
144
+ onCreate?(d: Drawing, c: ToolCtx): void;
145
+ /** Pixel positions of the edit handles, when they differ from the anchors. */
146
+ handlePoints?(d: Drawing, c: ToolCtx): Array<{
147
+ x: number;
148
+ y: number;
149
+ }>;
150
+ }
151
+ export declare const DEFAULT_STYLE: DrawingStyle;
152
+ export declare const SCHEMA_VERSION = 1;
153
+ export interface DrawingsState {
154
+ version: typeof SCHEMA_VERSION;
155
+ drawings: Drawing[];
156
+ }
package/package.json CHANGED
@@ -1,6 +1,55 @@
1
1
  {
2
2
  "name": "@alphacharts/drawings",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.1.1",
4
+ "description": "Chart drawing tools for alphacharts: 82 tools, undo/redo, magnet and templates.",
5
+ "keywords": [
6
+ "drawings",
7
+ "trendline",
8
+ "fibonacci",
9
+ "chart",
10
+ "trading"
11
+ ],
12
+ "license": "MIT",
13
+ "author": "Alphabench",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/alphabench/alphacharts.git",
17
+ "directory": "packages/drawings"
18
+ },
19
+ "homepage": "https://github.com/alphabench/alphacharts#readme",
20
+ "bugs": {
21
+ "url": "https://github.com/alphabench/alphacharts/issues"
22
+ },
23
+ "publishConfig": {
24
+ "access": "public"
25
+ },
26
+ "type": "module",
27
+ "sideEffects": false,
28
+ "main": "./dist/index.js",
29
+ "module": "./dist/index.js",
30
+ "types": "./dist/types/index.d.ts",
31
+ "exports": {
32
+ ".": {
33
+ "types": "./dist/types/index.d.ts",
34
+ "default": "./dist/index.js"
35
+ }
36
+ },
37
+ "files": [
38
+ "dist"
39
+ ],
40
+ "peerDependencies": {
41
+ "@alphacharts/core": "^0.1.0"
42
+ },
43
+ "devDependencies": {
44
+ "typescript": "5.9.3",
45
+ "vite": "8.3.1",
46
+ "vitest": "5.0.2",
47
+ "@alphacharts/core": "0.1.1"
48
+ },
49
+ "scripts": {
50
+ "build": "vite build && tsc -p tsconfig.build.json",
51
+ "typecheck": "tsc -p tsconfig.json",
52
+ "typecheck:dist": "tsc -p tsconfig.dist.json",
53
+ "test": "vitest run"
54
+ }
6
55
  }