@stocksharp/trading-controls 1.3.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.
Files changed (62) hide show
  1. package/README.md +113 -5
  2. package/dist/esm/chart-engine.js +15 -0
  3. package/dist/esm/chart-engine.js.map +1 -0
  4. package/dist/esm/control-types.js +4 -0
  5. package/dist/esm/control-types.js.map +1 -1
  6. package/dist/esm/equity-widget.js +261 -0
  7. package/dist/esm/equity-widget.js.map +1 -0
  8. package/dist/esm/heatmap-grid.js +271 -0
  9. package/dist/esm/heatmap-grid.js.map +1 -0
  10. package/dist/esm/index.js +19 -0
  11. package/dist/esm/index.js.map +1 -1
  12. package/dist/esm/optimization-heatmap-widget.js +303 -0
  13. package/dist/esm/optimization-heatmap-widget.js.map +1 -0
  14. package/dist/esm/option-smile-widget.js +252 -0
  15. package/dist/esm/option-smile-widget.js.map +1 -0
  16. package/dist/esm/pnl-curve.js +5 -1
  17. package/dist/esm/pnl-curve.js.map +1 -1
  18. package/dist/esm/surface-grid.js +282 -0
  19. package/dist/esm/surface-grid.js.map +1 -0
  20. package/dist/esm/surface-widget.js +379 -0
  21. package/dist/esm/surface-widget.js.map +1 -0
  22. package/dist/sstradingcontrols.js +1595 -168
  23. package/dist/sstradingcontrols.js.map +4 -4
  24. package/dist/types/chart-engine.d.ts +3 -0
  25. package/dist/types/chart-engine.d.ts.map +1 -0
  26. package/dist/types/control-types.d.ts +4 -0
  27. package/dist/types/control-types.d.ts.map +1 -1
  28. package/dist/types/equity-widget.d.ts +34 -0
  29. package/dist/types/equity-widget.d.ts.map +1 -0
  30. package/dist/types/heatmap-grid.d.ts +88 -0
  31. package/dist/types/heatmap-grid.d.ts.map +1 -0
  32. package/dist/types/index.d.ts +15 -0
  33. package/dist/types/index.d.ts.map +1 -1
  34. package/dist/types/optimization-heatmap-widget.d.ts +45 -0
  35. package/dist/types/optimization-heatmap-widget.d.ts.map +1 -0
  36. package/dist/types/option-smile-widget.d.ts +39 -0
  37. package/dist/types/option-smile-widget.d.ts.map +1 -0
  38. package/dist/types/pnl-curve.d.ts +3 -0
  39. package/dist/types/pnl-curve.d.ts.map +1 -1
  40. package/dist/types/surface-grid.d.ts +64 -0
  41. package/dist/types/surface-grid.d.ts.map +1 -0
  42. package/dist/types/surface-widget.d.ts +64 -0
  43. package/dist/types/surface-widget.d.ts.map +1 -0
  44. package/package.json +28 -2
  45. package/screenshots/equity.png +0 -0
  46. package/screenshots/optimization-surface.png +0 -0
  47. package/screenshots/optimization.png +0 -0
  48. package/screenshots/option-smile.png +0 -0
  49. package/screenshots/panels.jpg +0 -0
  50. package/src/chart-engine.global.ts +64 -0
  51. package/src/chart-engine.ts +29 -0
  52. package/src/control-types.ts +4 -0
  53. package/src/equity-widget.ts +289 -0
  54. package/src/heatmap-grid.ts +405 -0
  55. package/src/index.ts +46 -0
  56. package/src/optimization-heatmap-widget.ts +347 -0
  57. package/src/option-smile-widget.ts +281 -0
  58. package/src/pnl-curve.ts +13 -1
  59. package/src/surface-grid.ts +410 -0
  60. package/src/surface-widget.ts +457 -0
  61. package/styles/trading-controls.css +281 -0
  62. package/translation-keys.json +14 -1
@@ -1734,3 +1734,284 @@
1734
1734
  .terminal-panel::-webkit-scrollbar-corner {
1735
1735
  background: transparent;
1736
1736
  }
1737
+
1738
+ /* ---- Option smile ------------------------------------------------------- */
1739
+
1740
+ .option-smile-legend {
1741
+ display: flex;
1742
+ align-items: center;
1743
+ flex-wrap: wrap;
1744
+ gap: 4px 12px;
1745
+ padding: 4px 10px;
1746
+ font-size: 10px;
1747
+ color: var(--t-text-dim);
1748
+ border-bottom: 1px solid var(--t-border);
1749
+ flex-shrink: 0;
1750
+ }
1751
+
1752
+ /* What the vertical axis measures, said once in words; the gutter down the chart carries only the
1753
+ numbers. */
1754
+ .option-smile-axis {
1755
+ text-transform: uppercase;
1756
+ letter-spacing: 0.8px;
1757
+ }
1758
+
1759
+ .option-smile-key {
1760
+ display: inline-flex;
1761
+ align-items: center;
1762
+ gap: 4px;
1763
+ }
1764
+
1765
+ .option-smile-dot {
1766
+ width: 8px;
1767
+ height: 8px;
1768
+ border-radius: 50%;
1769
+ }
1770
+
1771
+ /* The same pair the desk tells the two sides apart by, so the legend agrees with the curves the
1772
+ host's canvas palette draws. */
1773
+ .option-smile-dot-call { background: var(--t-green); }
1774
+ .option-smile-dot-put { background: var(--t-red); }
1775
+
1776
+ /* At the far end of the row: a reading of the market, not a key to the chart. */
1777
+ .option-smile-spot { margin-left: auto; }
1778
+
1779
+ /* ---- Equity ------------------------------------------------------------- */
1780
+
1781
+ /* The figure the run ended at, beside the panel's name rather than adrift between it and the
1782
+ close button - the auto margin is what puts the header's slack on the right. Mono and
1783
+ unspaced, because it is a number in a strip of captions; its colour arrives as the host's
1784
+ own `pnl-positive` / `pnl-negative`. */
1785
+ .equity-last {
1786
+ margin-right: auto;
1787
+ padding-left: 8px;
1788
+ font-family: var(--t-mono);
1789
+ font-size: 12px;
1790
+ letter-spacing: 0;
1791
+ text-transform: none;
1792
+ color: var(--t-text);
1793
+ }
1794
+
1795
+ /* ---------------------------------------------------- optimisation heatmap */
1796
+
1797
+ /* The panel is the tooltip's containing block: the tooltip is placed in canvas
1798
+ coordinates and would otherwise anchor to the page. */
1799
+ .optimization-heatmap-panel {
1800
+ display: flex;
1801
+ flex-direction: column;
1802
+ position: relative;
1803
+ }
1804
+
1805
+ /* What the colours mean, beside the panel's own name. It captions the legend
1806
+ the control draws on the canvas, and living in the chrome costs the map no
1807
+ pixels and leaves the text selectable. */
1808
+ .heatmap-metric {
1809
+ margin-left: auto;
1810
+ margin-right: 8px;
1811
+ color: var(--t-text-bright);
1812
+ letter-spacing: 0.4px;
1813
+ }
1814
+
1815
+ /* The map fills the body, so the body stops scrolling and becomes a column:
1816
+ a canvas that grows to fit inside a box that grows to fit it never settles. */
1817
+ .optimization-heatmap-panel > .panel-body {
1818
+ display: flex;
1819
+ flex-direction: column;
1820
+ overflow: hidden;
1821
+ padding: 6px 8px 4px;
1822
+ }
1823
+
1824
+ /* Takes whatever height the panel has left; the control sizes its backing
1825
+ store to the device's pixels. */
1826
+ .heatmap-canvas {
1827
+ flex: 1;
1828
+ width: 100%;
1829
+ min-height: 0;
1830
+ display: block;
1831
+ }
1832
+
1833
+ .heatmap-empty {
1834
+ padding: 24px 0;
1835
+ text-align: center;
1836
+ color: var(--t-text-dim);
1837
+ font-family: var(--t-font);
1838
+ font-size: 11px;
1839
+ }
1840
+
1841
+ .heatmap-empty[hidden] { display: none; }
1842
+
1843
+ /* Placed by the control in canvas coordinates, which is why this is the one
1844
+ rule here carrying a `left` / `top` it does not declare. */
1845
+ .heatmap-tooltip {
1846
+ position: absolute;
1847
+ z-index: 20;
1848
+ min-width: 140px;
1849
+ padding: 6px 8px;
1850
+ background: var(--t-panel);
1851
+ border: 1px solid var(--t-border);
1852
+ border-radius: var(--t-radius);
1853
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
1854
+ font-family: var(--t-mono);
1855
+ font-size: 11px;
1856
+ line-height: 1.5;
1857
+ color: var(--t-text-bright);
1858
+ pointer-events: none;
1859
+ }
1860
+
1861
+ .heatmap-tooltip[hidden] { display: none; }
1862
+ .heatmap-tt-row { display: flex; justify-content: space-between; gap: 12px; }
1863
+ .heatmap-tt-label { color: var(--t-text-dim); }
1864
+ .heatmap-tt-value { font-weight: 600; }
1865
+
1866
+ /* The one row that is a statement rather than a pair. */
1867
+ .heatmap-tt-best {
1868
+ justify-content: center;
1869
+ margin-top: 2px;
1870
+ padding-top: 2px;
1871
+ border-top: 1px solid var(--t-border);
1872
+ color: var(--t-accent);
1873
+ font-weight: 600;
1874
+ text-transform: uppercase;
1875
+ letter-spacing: 0.6px;
1876
+ }
1877
+
1878
+ /* A phone has no cursor, so the panel's only way of reading a figure off the
1879
+ map is gone. The tooltip goes with it rather than sticking where a tap left
1880
+ it, and the metric caption keeps the header from wrapping. */
1881
+ @media (max-width: 768px) {
1882
+ .optimization-heatmap-panel .heatmap-tooltip { display: none; }
1883
+ .heatmap-metric { display: none; }
1884
+ }
1885
+
1886
+ /* ---- Optimisation surface ------------------------------------------------ */
1887
+
1888
+ /* The chart takes the whole body. `overflow: hidden` rather than the `auto` a panel body carries
1889
+ by default: the canvas is sized to the box it is given, so a scrollbar here would be a box the
1890
+ canvas then resized itself out of. */
1891
+ .terminal-panel.surface-panel > .panel-body {
1892
+ display: flex;
1893
+ flex-direction: column;
1894
+ overflow: hidden;
1895
+ }
1896
+
1897
+ .surface-chart {
1898
+ position: relative;
1899
+ flex: 1 1 auto;
1900
+ min-height: 120px;
1901
+ }
1902
+
1903
+ /* `touch-action: none` is what makes the surface turn under a thumb. Without it the browser
1904
+ claims the gesture for scrolling the page before the first pointermove ever arrives, and a
1905
+ drag on a phone moves the page instead of the landscape. */
1906
+ .surface-canvas {
1907
+ display: block;
1908
+ width: 100%;
1909
+ height: 100%;
1910
+ touch-action: none;
1911
+ cursor: grab;
1912
+ }
1913
+
1914
+ .surface-canvas:active { cursor: grabbing; }
1915
+
1916
+ /* What the landscape is of, beside the panel's name. */
1917
+ .surface-metric {
1918
+ margin-left: auto;
1919
+ margin-right: .4rem;
1920
+ color: var(--t-text-bright);
1921
+ font-variant-numeric: tabular-nums;
1922
+ }
1923
+
1924
+ .surface-empty {
1925
+ position: absolute;
1926
+ inset: 0;
1927
+ display: flex;
1928
+ align-items: center;
1929
+ justify-content: center;
1930
+ color: var(--t-text-dim);
1931
+ }
1932
+
1933
+ /* The one button in the header that is not a close: it puts the view back where it started,
1934
+ which is the way out of a rotation a reader has lost their bearings in. */
1935
+ .surface-reset-btn { margin-right: .2rem; }
1936
+
1937
+ /* The `hidden` attribute is nothing but `display: none` in the browser's own stylesheet, so any
1938
+ display of ours beats it - and a panel that gives an element `display: flex` and then hides it
1939
+ by attribute shows it regardless. Every control here hides something that way: the empty
1940
+ message a chart shows in place of itself, a legend with nothing to list. Scoped to this
1941
+ package's panels, so a host's own hidden elements keep whatever rules the host gave them. */
1942
+ .terminal-panel [hidden] { display: none !important; }
1943
+
1944
+ /* A drag on a chart turns it; without this the same drag paints a text selection across the
1945
+ panel, and the selection stays behind when the pointer goes up. */
1946
+ .surface-chart { user-select: none; -webkit-user-select: none; }
1947
+
1948
+ /* What the pointer is over, beside the run's own figure. Dim until there is something to say,
1949
+ so the header does not jump between two widths as the pointer enters and leaves the curve. */
1950
+
1951
+ /* What the pointer is over, in the smile's legend: the strike and both sides at it. Pushed to
1952
+ the end of the row so the key stays where it was when the readout appears and disappears. */
1953
+ /* ---- What the pointer is over ---------------------------------------------- */
1954
+
1955
+ /* The three panels that draw a chart answer for the point under the pointer, and the answer sits
1956
+ over the chart rather than in the panel header. Two reasons, and the second is the one that
1957
+ caught us: a reading about a point belongs beside that point, and a host is free to lift a panel
1958
+ header into a tab strip - which put the smile's strike and volatilities into a tab title.
1959
+
1960
+ `pointer-events: none` so the strip never swallows a drag meant for the chart under it. */
1961
+ .equity-hover,
1962
+ .option-smile-hover,
1963
+ .surface-readout {
1964
+ position: absolute;
1965
+ left: 8px;
1966
+ top: 6px;
1967
+ z-index: 2;
1968
+ pointer-events: none;
1969
+ font-variant-numeric: tabular-nums;
1970
+ white-space: nowrap;
1971
+ font-size: 11px;
1972
+ text-shadow: 0 0 3px var(--t-panel);
1973
+ }
1974
+
1975
+ .equity-hover { color: var(--t-text-dim); }
1976
+ .option-smile-hover { color: var(--t-text-bright); }
1977
+ .surface-readout { color: var(--t-text-bright); }
1978
+
1979
+ /* ---- The two chart panels ------------------------------------------------ */
1980
+
1981
+ /* Both hold @stocksharp/chart rather than a canvas of their own, so the container is what the
1982
+ engine measures: it needs a definite size, and `position: relative` so the message that stands
1983
+ in for an empty chart can sit over it. The body does not scroll: the engine sizes itself to the
1984
+ box it is given, so a scrollbar here would be a box it then resized itself out of. */
1985
+ .equity-chart,
1986
+ .option-smile-chart {
1987
+ position: relative;
1988
+ flex: 1 1 auto;
1989
+ min-height: 120px;
1990
+ min-width: 0;
1991
+ }
1992
+
1993
+ .terminal-panel.equity-panel > .panel-body,
1994
+ .terminal-panel.option-smile-panel > .panel-body {
1995
+ display: flex;
1996
+ flex-direction: column;
1997
+ overflow: hidden;
1998
+ }
1999
+
2000
+ /* Over the chart rather than in the flow, so an empty run does not change the box the engine
2001
+ was given to measure. */
2002
+ .equity-empty,
2003
+ .option-smile-empty {
2004
+ position: absolute;
2005
+ inset: 0;
2006
+ display: flex;
2007
+ align-items: center;
2008
+ justify-content: center;
2009
+ font-size: 11px;
2010
+ color: var(--t-text-dim);
2011
+ pointer-events: none;
2012
+ }
2013
+
2014
+ /* The way back out of a zoom. A reader who has looked closely at one stretch needs one gesture
2015
+ to see the whole run again, and hunting the double-click is not it. */
2016
+ .equity-reset-btn,
2017
+ .option-smile-reset-btn { margin-right: .2rem; }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$comment": "Generated from src/ by tools/check-translation-keys.mjs -- do not edit by hand. Every string here is passed to TradingHost.t(); a host that answers none of them renders these literally to the user. See README.md (\"Text arrives through t()\").",
3
- "count": 222,
3
+ "count": 235,
4
4
  "keys": [
5
5
  "Actions",
6
6
  "ActiveOrders",
@@ -19,6 +19,7 @@
19
19
  "Avbl",
20
20
  "AvgPrice",
21
21
  "BBO",
22
+ "Best",
22
23
  "BestBidOrOffer",
23
24
  "Bid",
24
25
  "BidOrders",
@@ -48,6 +49,7 @@
48
49
  "Debug",
49
50
  "Delta",
50
51
  "Dismiss",
52
+ "Equity",
51
53
  "Error",
52
54
  "Errors",
53
55
  "ExportToExcel",
@@ -82,6 +84,7 @@
82
84
  "HideHeaderRow",
83
85
  "HV",
84
86
  "ID",
87
+ "ImpliedVolatility",
85
88
  "IntrinsicValue",
86
89
  "IVAsk",
87
90
  "IVBid",
@@ -114,7 +117,9 @@
114
117
  "No trade history",
115
118
  "No trades yet",
116
119
  "NoActiveOrders",
120
+ "NoEquity",
117
121
  "NoLogMessages",
122
+ "NoOptimizationResults",
118
123
  "NoOptions",
119
124
  "NoStatistics",
120
125
  "NoStrategies",
@@ -124,9 +129,14 @@
124
129
  "OpenOrders",
125
130
  "OpenPositions",
126
131
  "OpenStrategy",
132
+ "OptimizationHeatmap",
133
+ "OptimizationHeatmapChart",
134
+ "OptimizationSurface",
135
+ "OptimizationSurfaceChart",
127
136
  "OptionChain",
128
137
  "OptionDesk",
129
138
  "OptionDeskActions",
139
+ "OptionSmile",
130
140
  "Order",
131
141
  "OrderBook",
132
142
  "OrderBookDepth",
@@ -158,10 +168,12 @@
158
168
  "Refresh",
159
169
  "Remove",
160
170
  "RemoveOrderbook",
171
+ "ResetView",
161
172
  "Reverse position",
162
173
  "Reverse position on {0}",
163
174
  "Rho",
164
175
  "RiskManagement",
176
+ "Runs",
165
177
  "SearchInstruments",
166
178
  "SellHotkey",
167
179
  "ShowAllColumns",
@@ -211,6 +223,7 @@
211
223
  "Trades",
212
224
  "Trading",
213
225
  "Type",
226
+ "Underlying",
214
227
  "Ungroup",
215
228
  "UnrealizedProfit",
216
229
  "USD",