Summary
Nice Chart logic is currently embedded in mm_trader and does not produce stable, natural-looking price action consistently. This issue proposes extracting that logic into a dedicated mm_nice_chart module, adding persistent market history, and introducing an independent simulation flow that generates an HTML report for visual comparison across multiple timeframes.
Motivation
The current behavior can create uneven candles, abrupt moves, and chart artifacts that do not resemble liquid market behavior. At the same time, exchange trade history endpoints usually provide only a short recent window, which is not enough for stable chart shaping over a 30-day visible horizon.
A separate Nice Chart module with database-backed history solves both architecture and quality problems: logic becomes reusable and testable, restart continuity improves, and future features (for example, external-asset-follow mode) can be added without reworking trader core behavior.
Detailed description
The core change is a service-style module in trade/mm_nice_chart.js that handles trade ingestion, candle construction, next-trade price calculation, and best-effort candle-close correction. mm_trader should call this module through soft dependency loading and immediately fall back to legacy behavior if the module is unavailable or returns invalid output. This preserves backward compatibility and avoids runtime failures.
History must be kept both in memory and in MongoDB, with 90-day retention and a 30-day working window for chart shaping. Runtime ingestion should deduplicate records and continue operating in degraded mode when fresh exchange data is temporarily unavailable, using accumulated history and emitting warning logs.
Price decisions from Nice Chart must stay within operational limits defined by spread boundaries, Price Watcher constraints, selected MM policy, and order book liquidity safety. Candle-close correction is best-effort in the last seconds of a candle and must not violate risk or execution safety rules.
An independent simulation feature should be added under trade/tests and runnable from manual.test.js via an explicit parameter. It must support two seed-data modes: a single snapshot from getTradesHistory() and getOrderBook(), or existing database history. The simulation output is an HTML page with a two-column layout: first row compares 15m Nice Chart vs 15m baseline, followed by Nice Chart views from 1m to 1d for qualitative evaluation.
Screenshots or videos
Examples of bad-looking chart

Biconomy, 15m timeframe

DigiFinex, 1h timeframe
Compare to a good-looking BTC chart

Biconomy, 15m timeframe
Alternatives
Keeping Nice Chart inside mm_trader is the lowest-effort option, but it increases coupling, makes testing harder, and slows down future extensions. A loop-driven standalone module with its own scheduling is another option, but it introduces additional state complexity earlier than needed. The chosen middle-ground is a service module with controlled integration points and optional simulation tooling.
Proposed technical implementation
The implementation should introduce trade/mm_nice_chart.js as a service module with explicit lifecycle and computation boundaries. At startup, mm_trader performs a soft load of the module and initializes it with current config, tradeParams, pair metadata, and required adapters. If the module cannot be loaded or initialized, mm_trader keeps its current behavior without interruption.
The Nice Chart module should maintain a lightweight in-memory working state and a persistent MongoDB history store. Runtime ingestion takes normalized records from getTradesHistory(), deduplicates by stable identity (tradeId, timestamp, side/price fallback), and updates a rolling dataset with 90-day retention. Candle construction should be timeframe-agnostic and built from the same trade stream, so simulation and runtime logic share the same aggregation path.
getNextPrice() should return a constrained target envelope rather than an unconstrained raw value. The envelope is then intersected with spread limits, Price Watcher bounds, and policy-dependent order book constraints in mm_trader before order placement. Candle-close correction should be invoked in a best-effort window near candle end, but only when execution safety checks pass.
The simulation path should reuse the same Nice Chart service primitives to avoid divergence between test and production behavior. trade/tests/manual.test.js should route to a dedicated simulation runner via a parameter. The runner executes baseline and Nice Chart scenarios over identical inputs, computes chart-quality metrics, and generates a static HTML report in trade/tests/reports with the required two-column visual layout.
For extensibility, data access should be abstracted behind a small source adapter in mm_nice_chart (tradesSource, optional future candlesSource) so adding getCandlesHistory() later does not require changing price-shaping logic.
Notes
This issue is intentionally scoped to spot trading. Perpetual support is out of scope for this iteration. The design should still keep extension points for optional candle endpoints (getCandlesHistory()) and future external trend-follow behavior.
Documentation updates should be included for simulation run instructions, mode selection, and output location. Logging should follow existing project conventions with explicit module and function context.
The feature is planned for Premium bot edition, while basic bot will continue using regular Trader module.
Verification checklist
Summary
Nice Chart logic is currently embedded in
mm_traderand does not produce stable, natural-looking price action consistently. This issue proposes extracting that logic into a dedicatedmm_nice_chartmodule, adding persistent market history, and introducing an independent simulation flow that generates an HTML report for visual comparison across multiple timeframes.Motivation
The current behavior can create uneven candles, abrupt moves, and chart artifacts that do not resemble liquid market behavior. At the same time, exchange trade history endpoints usually provide only a short recent window, which is not enough for stable chart shaping over a 30-day visible horizon.
A separate Nice Chart module with database-backed history solves both architecture and quality problems: logic becomes reusable and testable, restart continuity improves, and future features (for example, external-asset-follow mode) can be added without reworking trader core behavior.
Detailed description
The core change is a service-style module in
trade/mm_nice_chart.jsthat handles trade ingestion, candle construction, next-trade price calculation, and best-effort candle-close correction.mm_tradershould call this module through soft dependency loading and immediately fall back to legacy behavior if the module is unavailable or returns invalid output. This preserves backward compatibility and avoids runtime failures.History must be kept both in memory and in MongoDB, with 90-day retention and a 30-day working window for chart shaping. Runtime ingestion should deduplicate records and continue operating in degraded mode when fresh exchange data is temporarily unavailable, using accumulated history and emitting warning logs.
Price decisions from Nice Chart must stay within operational limits defined by spread boundaries, Price Watcher constraints, selected MM policy, and order book liquidity safety. Candle-close correction is best-effort in the last seconds of a candle and must not violate risk or execution safety rules.
An independent simulation feature should be added under
trade/testsand runnable frommanual.test.jsvia an explicit parameter. It must support two seed-data modes: a single snapshot fromgetTradesHistory()andgetOrderBook(), or existing database history. The simulation output is an HTML page with a two-column layout: first row compares 15m Nice Chart vs 15m baseline, followed by Nice Chart views from 1m to 1d for qualitative evaluation.Screenshots or videos
Examples of bad-looking chart
Compare to a good-looking BTC chart
Alternatives
Keeping Nice Chart inside
mm_traderis the lowest-effort option, but it increases coupling, makes testing harder, and slows down future extensions. A loop-driven standalone module with its own scheduling is another option, but it introduces additional state complexity earlier than needed. The chosen middle-ground is a service module with controlled integration points and optional simulation tooling.Proposed technical implementation
The implementation should introduce
trade/mm_nice_chart.jsas a service module with explicit lifecycle and computation boundaries. At startup,mm_traderperforms a soft load of the module and initializes it with currentconfig,tradeParams, pair metadata, and required adapters. If the module cannot be loaded or initialized,mm_traderkeeps its current behavior without interruption.The Nice Chart module should maintain a lightweight in-memory working state and a persistent MongoDB history store. Runtime ingestion takes normalized records from
getTradesHistory(), deduplicates by stable identity (tradeId, timestamp, side/price fallback), and updates a rolling dataset with 90-day retention. Candle construction should be timeframe-agnostic and built from the same trade stream, so simulation and runtime logic share the same aggregation path.getNextPrice()should return a constrained target envelope rather than an unconstrained raw value. The envelope is then intersected with spread limits, Price Watcher bounds, and policy-dependent order book constraints inmm_traderbefore order placement. Candle-close correction should be invoked in a best-effort window near candle end, but only when execution safety checks pass.The simulation path should reuse the same Nice Chart service primitives to avoid divergence between test and production behavior.
trade/tests/manual.test.jsshould route to a dedicated simulation runner via a parameter. The runner executes baseline and Nice Chart scenarios over identical inputs, computes chart-quality metrics, and generates a static HTML report intrade/tests/reportswith the required two-column visual layout.For extensibility, data access should be abstracted behind a small source adapter in
mm_nice_chart(tradesSource, optional futurecandlesSource) so addinggetCandlesHistory()later does not require changing price-shaping logic.Notes
This issue is intentionally scoped to spot trading. Perpetual support is out of scope for this iteration. The design should still keep extension points for optional candle endpoints (
getCandlesHistory()) and future external trend-follow behavior.Documentation updates should be included for simulation run instructions, mode selection, and output location. Logging should follow existing project conventions with explicit module and function context.
The feature is planned for Premium bot edition, while basic bot will continue using regular Trader module.
Verification checklist
mm_nice_chartis implemented as a separate module and integrated intomm_tradervia soft dependencymm_tradercontinues to run correctly whenmm_nice_chartis absentmanual.test.jswith a parameter