Releases: apexcharts/apexstock
Release list
apexstock@0.5.1
Full changelog: CHANGELOG.md · npm: https://www.npmjs.com/package/apexstock/v/0.5.1
Changed
-
The simple moving average is now the shared one from
apex-commons, and
every number it draws is unchanged. The same window arithmetic sat here and
in the analysis layer, so it moved to the package both depend on; the OHLC
accessor, the memo cache and the 2-decimal display rounding stay here, since
those belong to this product rather than to the average. Verified exact
rather than assumed: over 360,000 sampled positions (120 price-like series,
periods 5 to 200) the shared implementation and the one it replaces agreed on
every one.apex-commonsmoves from^0.4.0to^0.7.0and is inlined into
the bundle as before, which grows by 223 bytes.Only the simple average moved. The exponential average and the Bollinger
bands stay local on purpose and now say why in their own comments: the EMA
rounds inside its recursion, which the streaming steppers for EMA, MACD and
TSI reproduce step for step and an exactness test pins, and the bands measure
their deviation against the rounded middle band that is actually drawn.
Delegating either would change values the product displays. -
A window average no longer depends on how much history precedes it. This
was already true and is now a test, because the shared implementation could
have quietly cost it. Computing a rolling mean with a running total (add the
new value, subtract the old) is the obvious faster shape and makes the result
carry the rounding error of everything before it, so the same window averaged
inside a long series and averaged alone occasionally round to a different
cent. That property is what lets theappendData()path extend an indicator
by recomputing only the tail window and still match a full recompute exactly. -
The test harness and the examples now load the ApexCharts a user installs.
Nothing in the repo declared the engine it renders with: every e2e fixture,
example, and framework demo pulledapexcharts.jsfrom a sibling checkout on
the maintainer's disk. A clone plusyarn installcould not run the e2e suite
at all, and when it did run it validated whatever happened to be in that
directory, which is not what the manifest promises or what a user gets. The
Angular demo's lockfile shows how far that can drift: it had the engine pinned
at 5.15.2, two majors behind the peer range declared at the time. ApexCharts
is now a devDependency pinned to the same range as the peer; fixtures load
/node_modules/apexcharts/dist/apexcharts.jsfrom a server rooted at the repo
(it used to be rooted at the parent directory), and examples and demos use the
relative equivalent. No runtime code changed: the newly installed 7.1.0 is
byte identical to the checkout the suite had been running against, so the 83
e2e tests, visual baselines included, pass unchanged. -
The three framework wrappers ship at 0.2.2 with peer ranges that agree with
each other.react-apexstock,vue-apexstock, andngx-apexstockhad
gained theapexchartspeer without a release, so npm still served 0.2.1,
which declared no engine requirement at all. Bumping them surfaced a defect in
the pairing:apexstock: ">=0.5.0 <1"is the only range that agrees with
apexcharts: "^7.1.0", because apexstock 0.3.x requires^5.15.0and 0.4.x
requires^6.7.0. Left as">=0.3.0 <1"the two peers were mutually
unsatisfiable, andnpm ci(in the publish workflow) andnpm install(for a
user) both failed with ERESOLVE. Their lockfiles were stale for the same
reason and now resolve apexstock 0.5.0 and apexcharts 7.1.0.
vue-apexstock@0.2.2
Full changelog: CHANGELOG.md · npm: https://www.npmjs.com/package/vue-apexstock/v/0.2.2
The Vue 3 wrapper for ApexStock, published with provenance.
Wrapper releases track the core: see the CHANGELOG for what changed, and packages/vue-apexstock/README.md for the component API.
react-apexstock@0.2.2
Full changelog: CHANGELOG.md · npm: https://www.npmjs.com/package/react-apexstock/v/0.2.2
The React wrapper for ApexStock, published with provenance.
Wrapper releases track the core: see the CHANGELOG for what changed, and packages/react-apexstock/README.md for the component API.
ngx-apexstock@0.2.2
Full changelog: CHANGELOG.md · npm: https://www.npmjs.com/package/ngx-apexstock/v/0.2.2
The Angular wrapper for ApexStock, published with provenance.
Wrapper releases track the core: see the CHANGELOG for what changed, and packages/ngx-apexstock/README.md for the component API.
apexstock@0.5.0
Full changelog: CHANGELOG.md · npm: https://www.npmjs.com/package/apexstock/v/0.5.0
The largest release since the library went commercial: sixteen additions, seven
behaviour changes, fifteen fixes.
One breaking change. The apexcharts peer requirement moves to ^7.1.0
(was ^6.7.0). Upgrade both together:
npm install apexstock@0.5.0 apexcharts@^7.1.0Two reasons it had to move. The old range had gone stale, and did not admit the
7.x line that every example and test fixture here actually loads, so the suite
was validating a combination the manifest forbade. And the crosshair fix below
lives in ApexCharts 7.1.0: on a zoomed chart with indicators the crosshair drew
on the wrong bar, off by one bar-width per warm-up bar (259px three wheel
notches in, 2056px at nine), and the main chart and each oscillator pane
disagreed with each other because their warm-ups differ.
The headline additions are a financial-analysis workspace (getRangeStats,
getDrawdown, measureRange, a drawdown pane, weighted pane heights),
comparison v2 with baseline policies and a benchmark role, cross-chart
sync, event markers, an on-chart data legend, price-scale modes
(linear / log / percent / indexed), a theme preset pack with
registerTheme, toolbar customization, and a unified export() covering
png / svg / pdf / csv / json, the PDF written without adding a dependency.
Also new is rangeChanging, a per-frame companion to rangeChange. If you have
custom chrome that must follow a zoom gesture, subscribe to it: rangeChange
fires once when the gesture settles, by design, so chrome hung off it alone
freezes for the duration of a wheel zoom.
The three framework wrappers are released alongside at 0.2.2 with the matching
peer requirement.
Added
-
Drawdown as a first-class pane, and per-pane heights. Phase 4 of the
financial-analysis workspace (seeplans/financial-analysis-workspace.md):
price on top, how far underwater it is below, on one shared x-axis and zoom.updateIndicator("drawdown")toggles an analysis pane plotting percent below
the running peak, with zero pinned to the top of the axis (a drawdown is
never positive) and the deepest point labelled on the pane itself. It is an
ordinary oscillator-registry entry, so it inherits the whole pane machinery:
stacking with other panes, the shared zoom, the theme rebuild,getDataAt,
getState/setState, and the settings-free dropdown entry. No new pane
system, and no separate API.- It measures on the chart's
analysis.drawdownBasis, so the pane,
getRangeStats(), andgetDrawdown()cannot disagree, and the basis
round-trips in state with the pane. - It streams incrementally on
appendData: the state is the running peak, so
the step is O(1) with no warm-up period. The pane's "max" label is
re-asserted after each append, so a new deeper trough moves it instead of
leaving a stale line behind. - The indicators dropdown groups it under an Analysis heading (a new
optionalgroupon a registry entry), keeping analysis views distinct from
technical indicators without adding a second control. - Per-pane heights. Panes now divide the indicator area in proportion to a
relativeheightRatiorather than always evenly: the drawdown pane takes 1.4
shares (it is cumulative, so it earns the room) and everything else takes 1.
Configure withpanes: { drawdown: { heightRatio: 2 } }at construction, or
setPaneHeightRatio(key, ratio)/getPaneHeightRatios()at runtime (null
restores the pane's default). The heights always add up to the container
exactly, and the ratios you set are captured bygetState()as a newpanes
key.
See the README "The drawdown pane" section.
-
Comparison persists, and the analysis can be exported. Phase 5 of the
financial-analysis workspace (seeplans/financial-analysis-workspace.md).getState()gains acomparisonkey: the mode, benchmark, alignment policy,
and each instrument's name and color. Instrument data is deliberately not
captured: your app fetches it, it runs to thousands of bars per instrument,
and it would be stale the moment it was written to storage. SosetState()
restores the setup, keeps any instrument whose data is still loaded, and
emits the newcomparisonRestoreNeededevent with{ names }for the
rest, which the consumer re-supplies withaddComparison(the remembered
color is reapplied). A benchmark whose instrument has not come back yet is
remembered by name, with the primary filling the role until it does. Same
division of labour as the price lines' interactive callbacks.- Measurements need no state key of their own: a measurement is a
measure
drawing, so it already round-tripped insidedrawings. exportData/exportgaininclude, which carries the analysis into an
export and means something appropriate to each medium. Forcsv/json:
"indicators"adds one column per active indicator series (main-chart
overlays and oscillator panes,nullthrough each warm-up) and
"analysis"addsreturnanddrawdownper bar. Forpdf:"analysis"
sets a text summary below the chart image (the window's dates and bar count,
change, high, low, average, volume, annualized return, volatility, max
drawdown, and the comparison leaderboard when one is active), overridable
withsummary: string[]. The PDF summary followsrange, defaulting to the
visible window there, so the exported numbers describe what you were looking
at.- The OHLC columns are always present, so a CSV keeps round-tripping through
ApexStock.fromCSVwhatever you add, and an extra column whose name collides
with a spine column is suffixed rather than overwriting it. Range statistics
are a summary, not a per-bar value, so they are not columns; read them from
getRangeStats(). - The PDF summary is still dependency-free:
buildPdfFromJpeggrows the page
for a text band below the image and sets it in Helvetica, one of the PDF
base-14 fonts, so there is nothing to embed.
See the README "State Persistence" and "Exporting the analysis" sections.
-
Comparison v2: instrument alignment, baseline policies, indexed / relative /
ratio modes, the benchmark role, andgetComparisonStats(). Phase 3 of the
financial-analysis workspace (seeplans/financial-analysis-workspace.md):
comparison mode now answers "who's up more" fairly even when the instruments
do not share a calendar.- Every instrument, the primary included, is aligned onto one shared x grid
before anything is normalized, so a newer listing, a different holiday
calendar, or a missing day no longer skews the comparison.
setComparisonOptions({ join, fill, baseline, indexBase, source, rebaseRatio, resample })/getComparisonOptions()expose the policies:
join("union"by default, or"primary"to resample onto the primary's
bars, or"intersection") andfill("hold"by default, or"gap", or
"drop"). - A carried-forward value is used for the math but is not plotted, so a
line never shows a bar its instrument does not have.
getComparisonStats()reports how many points were filled.
resample: trueplots the filled grid instead (the default for
join: "primary", which exists to resample). - Baseline policies:
"common"(the new default) rebases at the first x
where every instrument has data; earlier history still plots, as a negative
percent, rather than being hidden."own"is the previous behavior, kept for
compatibility."visible"rebases to the left edge of the visible window and
follows the zoom. A number is an explicit x value. - Three new modes on top of
absoluteandpercent:indexed(the baseline
readsindexBase, default 100, the "100 = starting value" view),relative
(percentChange(asset) - percentChange(benchmark), in percentage points,
where zero means "kept pace"), andratio(asset / benchmark, rebased to
indexBase). - The benchmark is a role, not a ticker:
setComparisonBenchmark(name | "__primary__")/
getComparisonBenchmark()points it at any added instrument or the chart's
own symbol (the default). Inrelativeandratiomode the benchmark's own
line becomes the flat reference, so what everything is measured against is
visible on the chart. Removing that instrument hands the role back to the
primary. No symbol is hard-coded anywhere in the library. getComparisonStats({ from?, to? })returns the leaderboard ready to render:
one row per instrument (primary included) with change, excess return vs the
benchmark, high and low, volatility, worst drawdown, rank, and grid coverage.
The window runs from the baseline to the last observation, so with
baseline: "visible"the rows follow the zoom. Volatility and drawdown are
measured on each instrument's own observations, so a weekly line on a
daily grid is not annualized as if it had 252 bars a year.- New event
comparisonChange
({ reason, mode, benchmark, baseline, instruments, stats, warnings }),
carrying the recomputed leaderboard and skipped entirely when nothing is
subscribed.baselinereports the policy actually applied, which can fall
back to"own"when no x value has data for every instrument. - Declarative defaults via
analysis: { comparison: { mode, benchmark, join, fill, baseline, indexBase, source } }. A benchmark named there is remembered until its instrument is
added, with the primary filling the role (and saying so inwarnings) until
then. Unknown option values are warned about and ignored rathe...
- Every instrument, the primary included, is aligned onto one shared x grid