@stocksharp/trading-controls 1.2.0 → 1.4.0
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 +204 -17
- package/dist/esm/black-scholes.js +147 -0
- package/dist/esm/black-scholes.js.map +1 -0
- package/dist/esm/chart-engine.js +15 -0
- package/dist/esm/chart-engine.js.map +1 -0
- package/dist/esm/control-types.js +8 -0
- package/dist/esm/control-types.js.map +1 -1
- package/dist/esm/equity-widget.js +261 -0
- package/dist/esm/equity-widget.js.map +1 -0
- package/dist/esm/heatmap-grid.js +271 -0
- package/dist/esm/heatmap-grid.js.map +1 -0
- package/dist/esm/index.js +37 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/log-monitor-widget.js +265 -0
- package/dist/esm/log-monitor-widget.js.map +1 -0
- package/dist/esm/log-tree.js +96 -0
- package/dist/esm/log-tree.js.map +1 -0
- package/dist/esm/optimization-heatmap-widget.js +303 -0
- package/dist/esm/optimization-heatmap-widget.js.map +1 -0
- package/dist/esm/option-desk-widget.js +322 -0
- package/dist/esm/option-desk-widget.js.map +1 -0
- package/dist/esm/option-smile-widget.js +252 -0
- package/dist/esm/option-smile-widget.js.map +1 -0
- package/dist/esm/pnl-curve.js +133 -0
- package/dist/esm/pnl-curve.js.map +1 -0
- package/dist/esm/statistics-widget.js +194 -0
- package/dist/esm/statistics-widget.js.map +1 -0
- package/dist/esm/strategies-widget.js +348 -0
- package/dist/esm/strategies-widget.js.map +1 -0
- package/dist/esm/surface-grid.js +282 -0
- package/dist/esm/surface-grid.js.map +1 -0
- package/dist/esm/surface-widget.js +379 -0
- package/dist/esm/surface-widget.js.map +1 -0
- package/dist/sstradingcontrols.js +2982 -295
- package/dist/sstradingcontrols.js.map +4 -4
- package/dist/types/black-scholes.d.ts +28 -0
- package/dist/types/black-scholes.d.ts.map +1 -0
- package/dist/types/chart-engine.d.ts +3 -0
- package/dist/types/chart-engine.d.ts.map +1 -0
- package/dist/types/control-types.d.ts +8 -0
- package/dist/types/control-types.d.ts.map +1 -1
- package/dist/types/equity-widget.d.ts +34 -0
- package/dist/types/equity-widget.d.ts.map +1 -0
- package/dist/types/heatmap-grid.d.ts +88 -0
- package/dist/types/heatmap-grid.d.ts.map +1 -0
- package/dist/types/index.d.ts +31 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/log-monitor-widget.d.ts +42 -0
- package/dist/types/log-monitor-widget.d.ts.map +1 -0
- package/dist/types/log-tree.d.ts +34 -0
- package/dist/types/log-tree.d.ts.map +1 -0
- package/dist/types/optimization-heatmap-widget.d.ts +45 -0
- package/dist/types/optimization-heatmap-widget.d.ts.map +1 -0
- package/dist/types/option-desk-widget.d.ts +68 -0
- package/dist/types/option-desk-widget.d.ts.map +1 -0
- package/dist/types/option-smile-widget.d.ts +39 -0
- package/dist/types/option-smile-widget.d.ts.map +1 -0
- package/dist/types/pnl-curve.d.ts +46 -0
- package/dist/types/pnl-curve.d.ts.map +1 -0
- package/dist/types/statistics-widget.d.ts +29 -0
- package/dist/types/statistics-widget.d.ts.map +1 -0
- package/dist/types/strategies-widget.d.ts +63 -0
- package/dist/types/strategies-widget.d.ts.map +1 -0
- package/dist/types/surface-grid.d.ts +64 -0
- package/dist/types/surface-grid.d.ts.map +1 -0
- package/dist/types/surface-widget.d.ts +64 -0
- package/dist/types/surface-widget.d.ts.map +1 -0
- package/dist/types/trading-data.d.ts +9 -0
- package/dist/types/trading-data.d.ts.map +1 -1
- package/package.json +54 -3
- package/screenshots/equity.png +0 -0
- package/screenshots/log-monitor.png +0 -0
- package/screenshots/optimization-surface.png +0 -0
- package/screenshots/optimization.png +0 -0
- package/screenshots/option-desk.png +0 -0
- package/screenshots/option-smile.png +0 -0
- package/screenshots/panels.jpg +0 -0
- package/screenshots/statistics.png +0 -0
- package/screenshots/strategies.png +0 -0
- package/src/black-scholes.ts +199 -0
- package/src/chart-engine.global.ts +64 -0
- package/src/chart-engine.ts +29 -0
- package/src/control-types.ts +8 -0
- package/src/equity-widget.ts +289 -0
- package/src/heatmap-grid.ts +405 -0
- package/src/index.ts +87 -0
- package/src/log-monitor-widget.ts +312 -0
- package/src/log-tree.ts +131 -0
- package/src/optimization-heatmap-widget.ts +347 -0
- package/src/option-desk-widget.ts +422 -0
- package/src/option-smile-widget.ts +281 -0
- package/src/pnl-curve.ts +216 -0
- package/src/statistics-widget.ts +226 -0
- package/src/strategies-widget.ts +435 -0
- package/src/surface-grid.ts +410 -0
- package/src/surface-widget.ts +457 -0
- package/src/trading-data.ts +22 -0
- package/styles/trading-controls.css +637 -0
- package/translation-keys.json +83 -1
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { TradingHost } from './trading-host.js';
|
|
2
|
+
import { type PnlPoint } from './pnl-curve.js';
|
|
3
|
+
import { DataGrid, GridColumn } from '@stocksharp/grids/data-grid';
|
|
4
|
+
export declare const StrategyStates: {
|
|
5
|
+
readonly Stopped: "stopped";
|
|
6
|
+
readonly Starting: "starting";
|
|
7
|
+
readonly Started: "started";
|
|
8
|
+
readonly Stopping: "stopping";
|
|
9
|
+
};
|
|
10
|
+
export type StrategyState = typeof StrategyStates[keyof typeof StrategyStates];
|
|
11
|
+
export interface StrategyRow {
|
|
12
|
+
id: string;
|
|
13
|
+
name: string;
|
|
14
|
+
state: StrategyState | string;
|
|
15
|
+
online?: boolean;
|
|
16
|
+
tradingMode?: string;
|
|
17
|
+
portfolio?: string;
|
|
18
|
+
security?: string;
|
|
19
|
+
position?: number | null;
|
|
20
|
+
ordersCount?: number | null;
|
|
21
|
+
tradesCount?: number | null;
|
|
22
|
+
pnlChange?: number | null;
|
|
23
|
+
realized?: number | null;
|
|
24
|
+
unrealized?: number | null;
|
|
25
|
+
pnl?: PnlPoint[];
|
|
26
|
+
error?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface StrategiesActions {
|
|
29
|
+
start?(id: string): void;
|
|
30
|
+
stop?(id: string): void;
|
|
31
|
+
closePosition?(id: string): void;
|
|
32
|
+
openStrategy?(id: string): void;
|
|
33
|
+
riskRules?(id: string): void;
|
|
34
|
+
setTradingMode?(id: string, mode: string): void;
|
|
35
|
+
}
|
|
36
|
+
export interface StrategiesDeps extends StrategiesActions {
|
|
37
|
+
host: TradingHost;
|
|
38
|
+
tradingModes?: readonly string[];
|
|
39
|
+
}
|
|
40
|
+
export declare class StrategiesWidget {
|
|
41
|
+
static TYPE: "strategies";
|
|
42
|
+
rootEl: HTMLElement;
|
|
43
|
+
el: HTMLElement | null;
|
|
44
|
+
_host: TradingHost;
|
|
45
|
+
_deps: StrategiesDeps;
|
|
46
|
+
_closeBtn: HTMLElement | null;
|
|
47
|
+
_exportBtn: HTMLElement | null;
|
|
48
|
+
_rows: StrategyRow[];
|
|
49
|
+
_grid: DataGrid<StrategyRow> | null;
|
|
50
|
+
static create(hostEl: HTMLElement, state: Record<string, unknown>, deps: StrategiesDeps): StrategiesWidget;
|
|
51
|
+
static _buildRoot(host: TradingHost): HTMLElement;
|
|
52
|
+
constructor(rootEl: HTMLElement, _state: Record<string, unknown>, deps: StrategiesDeps);
|
|
53
|
+
dispose(): void;
|
|
54
|
+
update(rows: StrategyRow[]): void;
|
|
55
|
+
_export(): void;
|
|
56
|
+
_columns(): GridColumn<StrategyRow>[];
|
|
57
|
+
_stateCell(row: StrategyRow): string | Node;
|
|
58
|
+
_actionCell(row: StrategyRow): Node;
|
|
59
|
+
_positionCell(row: StrategyRow): string | Node;
|
|
60
|
+
_tradingCell(row: StrategyRow): string | Node;
|
|
61
|
+
_sparkline(row: StrategyRow): string | Node;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=strategies-widget.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strategies-widget.d.ts","sourceRoot":"","sources":["../../src/strategies-widget.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { type HeatBucket, type HeatCell, type HeatDirection, type HeatScale } from './heatmap-grid.js';
|
|
2
|
+
export interface SurfaceView {
|
|
3
|
+
yaw: number;
|
|
4
|
+
pitch: number;
|
|
5
|
+
zoom: number;
|
|
6
|
+
}
|
|
7
|
+
export interface SurfaceBox {
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
}
|
|
11
|
+
export interface SurfaceQuad {
|
|
12
|
+
points: [number, number][];
|
|
13
|
+
tint: number;
|
|
14
|
+
depth: number;
|
|
15
|
+
bucket: HeatBucket;
|
|
16
|
+
}
|
|
17
|
+
export interface SurfaceAxis {
|
|
18
|
+
from: [number, number];
|
|
19
|
+
to: [number, number];
|
|
20
|
+
axis: 'x' | 'y' | 'z';
|
|
21
|
+
ticks: SurfaceTick[];
|
|
22
|
+
}
|
|
23
|
+
export interface SurfaceTick {
|
|
24
|
+
at: [number, number];
|
|
25
|
+
label: string;
|
|
26
|
+
away: [number, number];
|
|
27
|
+
}
|
|
28
|
+
export interface SurfaceVertex {
|
|
29
|
+
at: [number, number];
|
|
30
|
+
x: string;
|
|
31
|
+
y: string;
|
|
32
|
+
value: number;
|
|
33
|
+
depth: number;
|
|
34
|
+
}
|
|
35
|
+
export interface SurfaceLayout {
|
|
36
|
+
quads: SurfaceQuad[];
|
|
37
|
+
axes: SurfaceAxis[];
|
|
38
|
+
vertices: SurfaceVertex[];
|
|
39
|
+
xValues: string[];
|
|
40
|
+
yValues: string[];
|
|
41
|
+
scale: HeatScale;
|
|
42
|
+
}
|
|
43
|
+
export interface SurfaceInput {
|
|
44
|
+
width: number;
|
|
45
|
+
height: number;
|
|
46
|
+
cells: readonly HeatCell[];
|
|
47
|
+
betterWhen: HeatDirection;
|
|
48
|
+
view: SurfaceView;
|
|
49
|
+
}
|
|
50
|
+
export declare const MIN_PITCH = 0.12;
|
|
51
|
+
export declare const MAX_PITCH = 1.45;
|
|
52
|
+
export declare const DEFAULT_VIEW: SurfaceView;
|
|
53
|
+
export declare function clampView(view: SurfaceView): SurfaceView;
|
|
54
|
+
export declare function dragView(view: SurfaceView, dx: number, dy: number): SurfaceView;
|
|
55
|
+
export declare function zoomView(view: SurfaceView, factor: number): SurfaceView;
|
|
56
|
+
export declare function project(nx: number, ny: number, nz: number, view: SurfaceView, box: SurfaceBox): {
|
|
57
|
+
x: number;
|
|
58
|
+
y: number;
|
|
59
|
+
depth: number;
|
|
60
|
+
};
|
|
61
|
+
export declare function surfaceLayout(input: SurfaceInput): SurfaceLayout | null;
|
|
62
|
+
export declare const SURFACE_HEIGHT_TICKS: readonly number[];
|
|
63
|
+
export declare function nearestVertex(vertices: readonly SurfaceVertex[], x: number, y: number, reach: number): SurfaceVertex | null;
|
|
64
|
+
//# sourceMappingURL=surface-grid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"surface-grid.d.ts","sourceRoot":"","sources":["../../src/surface-grid.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { TradingHost } from './trading-host.js';
|
|
2
|
+
import { type HeatCell, type HeatDirection } from './heatmap-grid.js';
|
|
3
|
+
import { type SurfaceLayout, type SurfaceVertex, type SurfaceView } from './surface-grid.js';
|
|
4
|
+
export interface SurfaceData {
|
|
5
|
+
xLabel: string;
|
|
6
|
+
yLabel: string;
|
|
7
|
+
metricLabel: string;
|
|
8
|
+
betterWhen: HeatDirection;
|
|
9
|
+
cells: HeatCell[];
|
|
10
|
+
}
|
|
11
|
+
export interface SurfaceDeps {
|
|
12
|
+
host: TradingHost;
|
|
13
|
+
}
|
|
14
|
+
export declare function wheelNotches(deltaY: number, deltaMode: number): number;
|
|
15
|
+
export declare class SurfaceWidget {
|
|
16
|
+
static TYPE: "optimizationSurface";
|
|
17
|
+
rootEl: HTMLElement;
|
|
18
|
+
canvasEl: HTMLCanvasElement | null;
|
|
19
|
+
_host: TradingHost;
|
|
20
|
+
_closeBtn: HTMLElement | null;
|
|
21
|
+
_resetBtn: HTMLElement | null;
|
|
22
|
+
_emptyEl: HTMLElement | null;
|
|
23
|
+
_ctx: CanvasRenderingContext2D | null;
|
|
24
|
+
_data: SurfaceData | null;
|
|
25
|
+
_view: SurfaceView;
|
|
26
|
+
_resizeObserver: ResizeObserver | null;
|
|
27
|
+
_pointers: Map<number, {
|
|
28
|
+
x: number;
|
|
29
|
+
y: number;
|
|
30
|
+
}>;
|
|
31
|
+
_pinch: number;
|
|
32
|
+
_layout: SurfaceLayout | null;
|
|
33
|
+
_hover: SurfaceVertex | null;
|
|
34
|
+
_hoverEl: HTMLElement | null;
|
|
35
|
+
static create(hostEl: HTMLElement, state: Record<string, unknown>, deps: SurfaceDeps): SurfaceWidget;
|
|
36
|
+
static _buildRoot(host: TradingHost): HTMLElement;
|
|
37
|
+
constructor(rootEl: HTMLElement, _state: Record<string, unknown>, deps: SurfaceDeps);
|
|
38
|
+
dispose(): void;
|
|
39
|
+
update(data: SurfaceData): void;
|
|
40
|
+
view(): SurfaceView;
|
|
41
|
+
resetView(): void;
|
|
42
|
+
_bindGestures(): void;
|
|
43
|
+
_setHover(x: number | null, y: number | null): void;
|
|
44
|
+
_renderHover(): void;
|
|
45
|
+
_pointerSpread(): number;
|
|
46
|
+
_render(): void;
|
|
47
|
+
_drawAxes(ctx: CanvasRenderingContext2D, layout: SurfaceLayout, palette: {
|
|
48
|
+
grid: string;
|
|
49
|
+
font: string;
|
|
50
|
+
}): void;
|
|
51
|
+
_tickLabel(axis: 'x' | 'y' | 'z', label: string, layout: SurfaceLayout): string;
|
|
52
|
+
_axisCaption(axis: 'x' | 'y' | 'z'): string;
|
|
53
|
+
_drawHover(ctx: CanvasRenderingContext2D, palette: {
|
|
54
|
+
up: string;
|
|
55
|
+
grid: string;
|
|
56
|
+
}): void;
|
|
57
|
+
_drawFloor(ctx: CanvasRenderingContext2D, layout: SurfaceLayout, colour: string): void;
|
|
58
|
+
_drawFaces(ctx: CanvasRenderingContext2D, layout: SurfaceLayout, palette: {
|
|
59
|
+
up: string;
|
|
60
|
+
down: string;
|
|
61
|
+
grid: string;
|
|
62
|
+
}): void;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=surface-widget.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"surface-widget.d.ts","sourceRoot":"","sources":["../../src/surface-widget.ts"],"names":[],"mappings":"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"}
|
|
@@ -41,6 +41,15 @@ export interface TradeRow {
|
|
|
41
41
|
order?: number | null;
|
|
42
42
|
orderId?: number | null;
|
|
43
43
|
}
|
|
44
|
+
export interface StatisticRow {
|
|
45
|
+
key: string;
|
|
46
|
+
category: string;
|
|
47
|
+
categoryText?: string;
|
|
48
|
+
order: number;
|
|
49
|
+
name: string;
|
|
50
|
+
description?: string;
|
|
51
|
+
value?: number | string | Date | null;
|
|
52
|
+
}
|
|
44
53
|
export interface InstrumentRow {
|
|
45
54
|
symbol?: string;
|
|
46
55
|
name?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trading-data.d.ts","sourceRoot":"","sources":["../../src/trading-data.ts"],"names":[],"mappings":"AA2BA,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;AAIxC,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;AAIxC,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,CAAC;AAG1C,MAAM,WAAW,WAAW;IACxB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAI5B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAGD,MAAM,WAAW,UAAU;IACvB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAGD,MAAM,WAAW,QAAQ;IAGrB,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAGnB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAIzB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,EAAE,WAAW,CAAC;IAGrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAGD,MAAM,WAAW,QAAQ;IACrB,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAGnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAGtB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;
|
|
1
|
+
{"version":3,"file":"trading-data.d.ts","sourceRoot":"","sources":["../../src/trading-data.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stocksharp/trading-controls",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Browser trading controls for StockSharp: order blotters, positions, trade history, watchlist and trade feed, each built against one host port and rendering its own DOM.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"author": {
|
|
@@ -85,6 +85,42 @@
|
|
|
85
85
|
"types": "./dist/types/tradefeed-widget.d.ts",
|
|
86
86
|
"import": "./dist/esm/tradefeed-widget.js"
|
|
87
87
|
},
|
|
88
|
+
"./statistics-widget": {
|
|
89
|
+
"types": "./dist/types/statistics-widget.d.ts",
|
|
90
|
+
"import": "./dist/esm/statistics-widget.js"
|
|
91
|
+
},
|
|
92
|
+
"./strategies-widget": {
|
|
93
|
+
"types": "./dist/types/strategies-widget.d.ts",
|
|
94
|
+
"import": "./dist/esm/strategies-widget.js"
|
|
95
|
+
},
|
|
96
|
+
"./log-monitor-widget": {
|
|
97
|
+
"types": "./dist/types/log-monitor-widget.d.ts",
|
|
98
|
+
"import": "./dist/esm/log-monitor-widget.js"
|
|
99
|
+
},
|
|
100
|
+
"./option-desk-widget": {
|
|
101
|
+
"types": "./dist/types/option-desk-widget.d.ts",
|
|
102
|
+
"import": "./dist/esm/option-desk-widget.js"
|
|
103
|
+
},
|
|
104
|
+
"./option-smile-widget": {
|
|
105
|
+
"types": "./dist/types/option-smile-widget.d.ts",
|
|
106
|
+
"import": "./dist/esm/option-smile-widget.js"
|
|
107
|
+
},
|
|
108
|
+
"./equity-widget": {
|
|
109
|
+
"types": "./dist/types/equity-widget.d.ts",
|
|
110
|
+
"import": "./dist/esm/equity-widget.js"
|
|
111
|
+
},
|
|
112
|
+
"./optimization-heatmap-widget": {
|
|
113
|
+
"types": "./dist/types/optimization-heatmap-widget.d.ts",
|
|
114
|
+
"import": "./dist/esm/optimization-heatmap-widget.js"
|
|
115
|
+
},
|
|
116
|
+
"./surface-widget": {
|
|
117
|
+
"types": "./dist/types/surface-widget.d.ts",
|
|
118
|
+
"import": "./dist/esm/surface-widget.js"
|
|
119
|
+
},
|
|
120
|
+
"./trading-data": {
|
|
121
|
+
"types": "./dist/types/trading-data.d.ts",
|
|
122
|
+
"import": "./dist/esm/trading-data.js"
|
|
123
|
+
},
|
|
88
124
|
"./source": "./src/index.ts",
|
|
89
125
|
"./source/trading-host": "./src/trading-host.ts",
|
|
90
126
|
"./source/control-types": "./src/control-types.ts",
|
|
@@ -97,6 +133,18 @@
|
|
|
97
133
|
"./source/order-entry-widget": "./src/order-entry-widget.ts",
|
|
98
134
|
"./source/orderbook-widget": "./src/orderbook-widget.ts",
|
|
99
135
|
"./source/tradefeed-widget": "./src/tradefeed-widget.ts",
|
|
136
|
+
"./source/statistics-widget": "./src/statistics-widget.ts",
|
|
137
|
+
"./source/strategies-widget": "./src/strategies-widget.ts",
|
|
138
|
+
"./source/log-monitor-widget": "./src/log-monitor-widget.ts",
|
|
139
|
+
"./source/option-desk-widget": "./src/option-desk-widget.ts",
|
|
140
|
+
"./source/option-smile-widget": "./src/option-smile-widget.ts",
|
|
141
|
+
"./source/chart-engine": "./src/chart-engine.ts",
|
|
142
|
+
"./source/equity-widget": "./src/equity-widget.ts",
|
|
143
|
+
"./source/optimization-heatmap-widget": "./src/optimization-heatmap-widget.ts",
|
|
144
|
+
"./source/heatmap-grid": "./src/heatmap-grid.ts",
|
|
145
|
+
"./source/surface-widget": "./src/surface-widget.ts",
|
|
146
|
+
"./source/surface-grid": "./src/surface-grid.ts",
|
|
147
|
+
"./source/trading-data": "./src/trading-data.ts",
|
|
100
148
|
"./styles.css": "./styles/trading-controls.css",
|
|
101
149
|
"./theme.css": "./styles/theme.css",
|
|
102
150
|
"./translation-keys.json": "./translation-keys.json",
|
|
@@ -136,13 +184,16 @@
|
|
|
136
184
|
"release:major": "npm version major -m \"chore: release v%s\""
|
|
137
185
|
},
|
|
138
186
|
"dependencies": {
|
|
139
|
-
"@stocksharp/grids": "^1.
|
|
187
|
+
"@stocksharp/grids": "^1.2.1"
|
|
140
188
|
},
|
|
141
189
|
"devDependencies": {
|
|
142
|
-
"@stocksharp/chart": "^
|
|
190
|
+
"@stocksharp/chart": "^2.4.0",
|
|
143
191
|
"@types/node": "^24.0.0",
|
|
144
192
|
"dockview-core": "^6.6.1",
|
|
145
193
|
"esbuild": "^0.25.0",
|
|
146
194
|
"typescript": "^5.8.0"
|
|
195
|
+
},
|
|
196
|
+
"peerDependencies": {
|
|
197
|
+
"@stocksharp/chart": "^2.1.0"
|
|
147
198
|
}
|
|
148
199
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/screenshots/panels.jpg
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
// Option pricing and the greeks, as pure functions.
|
|
2
|
+
//
|
|
3
|
+
// The desktop desk gets these from StockSharp.Algo.Derivatives, which a browser cannot call. A
|
|
4
|
+
// host could compute them and send them down, and one that already does should - the desk takes
|
|
5
|
+
// them either way. But a host that has bid, ask and an expiry has everything the arithmetic
|
|
6
|
+
// needs, and making it stand up a pricing service before it can draw a chain is a poor trade.
|
|
7
|
+
//
|
|
8
|
+
// So the maths ships, and it ships here, apart from the control: a wrong greek is not visible
|
|
9
|
+
// on screen the way a wrong column is, and the only defence is checking the numbers against
|
|
10
|
+
// values that are known.
|
|
11
|
+
//
|
|
12
|
+
// Conventions follow the desk that reads them, not the textbook: vega is per one point of
|
|
13
|
+
// volatility, theta is per calendar day, and rho is per one point of rate - the units a trader
|
|
14
|
+
// works in, rather than per 1.0 of each, which nobody quotes.
|
|
15
|
+
|
|
16
|
+
export const OptionTypes = {
|
|
17
|
+
Call: 'call',
|
|
18
|
+
Put: 'put',
|
|
19
|
+
} as const;
|
|
20
|
+
|
|
21
|
+
export type OptionType = typeof OptionTypes[keyof typeof OptionTypes];
|
|
22
|
+
|
|
23
|
+
/// Everything a price depends on. Time is in years, rates and volatility are fractions - 0.05
|
|
24
|
+
/// is five percent, not five.
|
|
25
|
+
export interface OptionInputs {
|
|
26
|
+
assetPrice: number;
|
|
27
|
+
strike: number;
|
|
28
|
+
/// Years remaining. Zero once expired, which makes every greek zero and the premium
|
|
29
|
+
/// intrinsic.
|
|
30
|
+
timeToExpiry: number;
|
|
31
|
+
riskFree: number;
|
|
32
|
+
dividend: number;
|
|
33
|
+
/// Volatility, as a fraction.
|
|
34
|
+
deviation: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface Greeks {
|
|
38
|
+
delta: number;
|
|
39
|
+
gamma: number;
|
|
40
|
+
/// Per one point of volatility.
|
|
41
|
+
vega: number;
|
|
42
|
+
/// Per calendar day.
|
|
43
|
+
theta: number;
|
|
44
|
+
/// Per one point of rate.
|
|
45
|
+
rho: number;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const SQRT_2PI = Math.sqrt(2 * Math.PI);
|
|
49
|
+
const DAYS_IN_YEAR = 365;
|
|
50
|
+
|
|
51
|
+
/// The standard normal CDF.
|
|
52
|
+
///
|
|
53
|
+
/// Hart's rational approximation, which is what pricing libraries use and what a desk's numbers
|
|
54
|
+
/// are expected to agree with: accurate to about 1e-15 across the range, and exactly a half at
|
|
55
|
+
/// the mean rather than nearly so. The cheaper Abramowitz-and-Stegun fit is good to 1e-7, which
|
|
56
|
+
/// sounds like enough until a greek that should be symmetric is not.
|
|
57
|
+
export function normalCdf(x: number): number {
|
|
58
|
+
const z = Math.abs(x);
|
|
59
|
+
|
|
60
|
+
// Beyond this the tail is smaller than double precision can carry anyway.
|
|
61
|
+
if (z > 37) return x > 0 ? 1 : 0;
|
|
62
|
+
|
|
63
|
+
const e = Math.exp(-(z * z) / 2);
|
|
64
|
+
let tail: number;
|
|
65
|
+
|
|
66
|
+
if (z < 7.07106781186547) {
|
|
67
|
+
let b = 3.52624965998911e-02 * z + 0.700383064443688;
|
|
68
|
+
b = b * z + 6.37396220353165;
|
|
69
|
+
b = b * z + 33.912866078383;
|
|
70
|
+
b = b * z + 112.079291497871;
|
|
71
|
+
b = b * z + 221.213596169931;
|
|
72
|
+
b = b * z + 220.206867912376;
|
|
73
|
+
|
|
74
|
+
let d = 8.83883476483184e-02 * z + 1.75566716318264;
|
|
75
|
+
d = d * z + 16.064177579207;
|
|
76
|
+
d = d * z + 86.7807322029461;
|
|
77
|
+
d = d * z + 296.564248779674;
|
|
78
|
+
d = d * z + 637.333633378831;
|
|
79
|
+
d = d * z + 793.826512519948;
|
|
80
|
+
d = d * z + 440.413735824752;
|
|
81
|
+
|
|
82
|
+
tail = (e * b) / d;
|
|
83
|
+
} else {
|
|
84
|
+
// A continued fraction, which is what stays accurate once the polynomial ratio above
|
|
85
|
+
// starts losing digits to cancellation.
|
|
86
|
+
let b = z + 0.65;
|
|
87
|
+
b = z + 4 / b;
|
|
88
|
+
b = z + 3 / b;
|
|
89
|
+
b = z + 2 / b;
|
|
90
|
+
b = z + 1 / b;
|
|
91
|
+
tail = e / (b * 2.506628274631);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return x > 0 ? 1 - tail : tail;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/// The standard normal density.
|
|
98
|
+
export function normalPdf(x: number): number {
|
|
99
|
+
return Math.exp(-0.5 * x * x) / SQRT_2PI;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/// d1, or zero when there is no time or no volatility for the division to mean anything.
|
|
103
|
+
export function d1(inputs: OptionInputs): number {
|
|
104
|
+
const { assetPrice, strike, timeToExpiry, riskFree, dividend, deviation } = inputs;
|
|
105
|
+
const spread = deviation * Math.sqrt(timeToExpiry);
|
|
106
|
+
|
|
107
|
+
if (spread === 0 || assetPrice <= 0 || strike <= 0) return 0;
|
|
108
|
+
|
|
109
|
+
return (Math.log(assetPrice / strike) + (riskFree - dividend + (deviation * deviation) / 2) * timeToExpiry) / spread;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/// d2, which is d1 less one standard deviation of the remaining time.
|
|
113
|
+
export function d2(inputs: OptionInputs): number {
|
|
114
|
+
const spread = inputs.deviation * Math.sqrt(inputs.timeToExpiry);
|
|
115
|
+
return spread === 0 ? 0 : d1(inputs) - spread;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/// What the option is worth.
|
|
119
|
+
///
|
|
120
|
+
/// At expiry, or with no volatility, that is its intrinsic value - the formula degenerates to
|
|
121
|
+
/// exactly that, and saying so explicitly keeps a zero denominator out of the general case.
|
|
122
|
+
export function premium(type: OptionType, inputs: OptionInputs): number {
|
|
123
|
+
const { assetPrice, strike, timeToExpiry, riskFree, dividend, deviation } = inputs;
|
|
124
|
+
|
|
125
|
+
if (timeToExpiry <= 0 || deviation <= 0)
|
|
126
|
+
return Math.max(0, type === OptionTypes.Call ? assetPrice - strike : strike - assetPrice);
|
|
127
|
+
|
|
128
|
+
const a = d1(inputs);
|
|
129
|
+
const b = d2(inputs);
|
|
130
|
+
const carried = assetPrice * Math.exp(-dividend * timeToExpiry);
|
|
131
|
+
const discounted = strike * Math.exp(-riskFree * timeToExpiry);
|
|
132
|
+
|
|
133
|
+
return type === OptionTypes.Call
|
|
134
|
+
? carried * normalCdf(a) - discounted * normalCdf(b)
|
|
135
|
+
: discounted * normalCdf(-b) - carried * normalCdf(-a);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/// Every greek at once: they share d1, and computing them together is both cheaper and the only
|
|
139
|
+
/// way they are guaranteed to describe the same moment.
|
|
140
|
+
export function greeks(type: OptionType, inputs: OptionInputs): Greeks {
|
|
141
|
+
const { assetPrice, strike, timeToExpiry, riskFree, dividend, deviation } = inputs;
|
|
142
|
+
const sign = type === OptionTypes.Call ? 1 : -1;
|
|
143
|
+
|
|
144
|
+
if (timeToExpiry <= 0 || deviation <= 0 || assetPrice <= 0) {
|
|
145
|
+
// An expired option still has a delta - it is one or nothing, depending on which side of
|
|
146
|
+
// the strike it finished. Everything else has stopped moving.
|
|
147
|
+
const inTheMoney = type === OptionTypes.Call ? assetPrice > strike : assetPrice < strike;
|
|
148
|
+
return { delta: inTheMoney ? sign : 0, gamma: 0, vega: 0, theta: 0, rho: 0 };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const a = d1(inputs);
|
|
152
|
+
const b = d2(inputs);
|
|
153
|
+
const sqrtT = Math.sqrt(timeToExpiry);
|
|
154
|
+
const density = normalPdf(a);
|
|
155
|
+
const carry = Math.exp(-dividend * timeToExpiry);
|
|
156
|
+
const discount = Math.exp(-riskFree * timeToExpiry);
|
|
157
|
+
|
|
158
|
+
const delta = sign * carry * normalCdf(sign * a);
|
|
159
|
+
const gamma = (carry * density) / (assetPrice * deviation * sqrtT);
|
|
160
|
+
|
|
161
|
+
// Scaled the way a desk quotes them: vega per one volatility point, rho per one rate point,
|
|
162
|
+
// theta per calendar day.
|
|
163
|
+
const vega = assetPrice * carry * density * sqrtT * 0.01;
|
|
164
|
+
const rho = sign * strike * timeToExpiry * discount * normalCdf(sign * b) * 0.01;
|
|
165
|
+
|
|
166
|
+
const theta = (
|
|
167
|
+
-(assetPrice * carry * density * deviation) / (2 * sqrtT)
|
|
168
|
+
- sign * riskFree * strike * discount * normalCdf(sign * b)
|
|
169
|
+
+ sign * dividend * assetPrice * carry * normalCdf(sign * a)
|
|
170
|
+
) / DAYS_IN_YEAR;
|
|
171
|
+
|
|
172
|
+
return { delta, gamma, vega, theta, rho };
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/// The volatility that would produce this price, or null when none would.
|
|
176
|
+
///
|
|
177
|
+
/// Bisection rather than Newton: vega collapses far from the money and deep in time, and a
|
|
178
|
+
/// Newton step divided by a vanishing vega walks off to nonsense. Halving cannot, and forty
|
|
179
|
+
/// steps over a range this wide is finer than any quote.
|
|
180
|
+
export function impliedVolatility(type: OptionType, inputs: OptionInputs, price: number): number | null {
|
|
181
|
+
if (!(price > 0) || inputs.timeToExpiry <= 0) return null;
|
|
182
|
+
|
|
183
|
+
const at = (deviation: number): number => premium(type, { ...inputs, deviation });
|
|
184
|
+
|
|
185
|
+
let low = 1e-6;
|
|
186
|
+
let high = 5;
|
|
187
|
+
|
|
188
|
+
// A price outside what any volatility in that range can produce has no answer, and
|
|
189
|
+
// returning the nearest bound would be a number that means nothing.
|
|
190
|
+
if (price < at(low) || price > at(high)) return null;
|
|
191
|
+
|
|
192
|
+
for (let step = 0; step < 60; step++) {
|
|
193
|
+
const mid = (low + high) / 2;
|
|
194
|
+
if (at(mid) < price) low = mid;
|
|
195
|
+
else high = mid;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return (low + high) / 2;
|
|
199
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// The chart engine, off the global its own bundle publishes.
|
|
2
|
+
//
|
|
3
|
+
// Only the IIFE build uses this file: `build.mjs` points `./chart-engine.js` here, so the browser
|
|
4
|
+
// bundle carries no copy of @stocksharp/chart. A page that loads `sschart.js` and
|
|
5
|
+
// `sstradingcontrols.js` would otherwise hold two of them - a megabyte twice, and two registries
|
|
6
|
+
// of series definitions that do not recognise each other's, so a series added through one engine
|
|
7
|
+
// is invisible to the other.
|
|
8
|
+
//
|
|
9
|
+
// Everything an npm consumer sees goes through `chart-engine.ts` and imports the package
|
|
10
|
+
// properly; this exists because a script tag has no module resolution to do that with.
|
|
11
|
+
import type {
|
|
12
|
+
TimedSeriesData,
|
|
13
|
+
AreaData as EngineAreaData,
|
|
14
|
+
CrosshairEvent as EngineCrosshairEvent,
|
|
15
|
+
IChartApi as EngineChartApi,
|
|
16
|
+
ISeriesApi as EngineSeriesApi,
|
|
17
|
+
LineData as EngineLineData,
|
|
18
|
+
SeriesOptions as EngineSeriesOptions,
|
|
19
|
+
Time as EngineTime,
|
|
20
|
+
} from '@stocksharp/chart';
|
|
21
|
+
|
|
22
|
+
export type AreaData = EngineAreaData;
|
|
23
|
+
export type CrosshairEvent = EngineCrosshairEvent;
|
|
24
|
+
export type IChartApi = EngineChartApi;
|
|
25
|
+
export type ISeriesApi<T extends TimedSeriesData> = EngineSeriesApi<T>;
|
|
26
|
+
export type LineData = EngineLineData;
|
|
27
|
+
export type SeriesOptions = EngineSeriesOptions;
|
|
28
|
+
export type Time = EngineTime;
|
|
29
|
+
|
|
30
|
+
/// The global `@stocksharp/chart`'s own bundle assigns itself to.
|
|
31
|
+
interface ChartGlobal {
|
|
32
|
+
createChart: typeof import('@stocksharp/chart').createChart;
|
|
33
|
+
AreaSeries: typeof import('@stocksharp/chart').AreaSeries;
|
|
34
|
+
LineSeries: typeof import('@stocksharp/chart').LineSeries;
|
|
35
|
+
CrosshairMode: typeof import('@stocksharp/chart').CrosshairMode;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function engine(): ChartGlobal {
|
|
39
|
+
const found = (globalThis as { SSChart?: ChartGlobal }).SSChart;
|
|
40
|
+
if (found === undefined || found === null) {
|
|
41
|
+
// Named plainly, because the fix is one script tag and a message that only says
|
|
42
|
+
// "createChart is not a function" sends a reader into this package instead.
|
|
43
|
+
throw new Error(
|
|
44
|
+
'The chart panels need @stocksharp/chart. Load its bundle (sschart.js) before '
|
|
45
|
+
+ 'sstradingcontrols.js, or import this package from npm rather than as a script.');
|
|
46
|
+
}
|
|
47
|
+
return found;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Read through on every call rather than captured at load: a script tag order that puts this
|
|
51
|
+
// bundle first would otherwise fail permanently instead of only until the engine arrives.
|
|
52
|
+
export const createChart: ChartGlobal['createChart'] = (container, options) => engine().createChart(container, options);
|
|
53
|
+
|
|
54
|
+
export const AreaSeries = new Proxy({} as ChartGlobal['AreaSeries'], {
|
|
55
|
+
get: (_target, key) => (engine().AreaSeries as unknown as Record<string | symbol, unknown>)[key],
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
export const LineSeries = new Proxy({} as ChartGlobal['LineSeries'], {
|
|
59
|
+
get: (_target, key) => (engine().LineSeries as unknown as Record<string | symbol, unknown>)[key],
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
export const CrosshairMode = new Proxy({} as ChartGlobal['CrosshairMode'], {
|
|
63
|
+
get: (_target, key) => (engine().CrosshairMode as unknown as Record<string | symbol, unknown>)[key],
|
|
64
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// The chart engine, in one place.
|
|
2
|
+
//
|
|
3
|
+
// Two panels here are charts rather than drawings - an equity curve over time and a smile over
|
|
4
|
+
// strike - and @stocksharp/chart already does what a chart does: a crosshair that names the
|
|
5
|
+
// point under the pointer, a wheel that zooms about it, a drag that pans, tick labels that pick
|
|
6
|
+
// their own step. Re-implementing that was two engines and a poorer result, so it is a peer
|
|
7
|
+
// dependency now and the panels are built on it.
|
|
8
|
+
//
|
|
9
|
+
// Every import of it goes through this module, for one reason: the IIFE bundle must NOT inline
|
|
10
|
+
// the engine. A page that loads `sschart.js` and `sstradingcontrols.js` would otherwise hold two
|
|
11
|
+
// copies of it - a megabyte twice over, and two registries of series definitions that do not
|
|
12
|
+
// recognise each other's. `build.mjs` points this specifier at `chart-engine.global.ts` for that
|
|
13
|
+
// build, which reads the engine off the global the chart's own bundle publishes.
|
|
14
|
+
export {
|
|
15
|
+
AreaSeries,
|
|
16
|
+
CrosshairMode,
|
|
17
|
+
LineSeries,
|
|
18
|
+
createChart,
|
|
19
|
+
} from '@stocksharp/chart';
|
|
20
|
+
|
|
21
|
+
export type {
|
|
22
|
+
AreaData,
|
|
23
|
+
CrosshairEvent,
|
|
24
|
+
IChartApi,
|
|
25
|
+
ISeriesApi,
|
|
26
|
+
LineData,
|
|
27
|
+
SeriesOptions,
|
|
28
|
+
Time,
|
|
29
|
+
} from '@stocksharp/chart';
|