Repository navigation
Releases: AmirMohammadBazdar/AlgoTradeKit
Release list
v1.2.0 - Notifications
[1.2.0] — 2026-10-23
Notifications. A trading session's events, chart pictures, price alerts and a
backtest's report go to Telegram, Discord, e-mail or a webhook, and Telegram
takes commands back. Trading never waits for a message, and nothing changes for
code that asks for none.
Added
notifymodule andTelegramNotifier— one bot and its named chats:
people, groups, channels and forum topics.TelegramChat(chat_id, thread_id=, silent=, events=, symbols=)gives a chat its own topic, sound and filters. The
token and every chat are checked when the notifier is created, with a sentence
saying what to fix, andTelegramNotifier.find_chats(token)lists the chats
that wrote to the bot.send_text()fills{time},{date},{symbol},
{price}and{header};timezone=,proxy=(HTTP, or SOCKS with the
[notify]extra) andtemplates=shape what goes out.KIND_*names every
kind of message.- A queue per notifier — every send waits its turn on the notifier's own
thread: paced to the service's limits, retried after an error, held through an
outage, and marked «⏱ N min late» when it arrives late. - Trading events to your chats —
TraderConfig(notifiers=[...]), for
run_liveandTraderalike: signals, opens, risk-free moves, TP levels,
closes, exit signals, the daily loss limit, reconciles, errors, the start and
the stop, and a summary of the day at midnight in the notifier's time zone. A
trade's later messages reply to its open. A chat that takessl_movesees each
move of the stop as an edit of the open message; by default a chat takes every
kind but that one. StartEvent,StopEventandMessageEventon the event stream, printed
by the terminal log too, andBaseStrategy.notify(text): a strategy's own
message, sent on a newly closed live candle, and never in a backtest, during
the seed or on a forming candle.- Chart pictures —
images={"open", "close"}puts a picture of the pair's
chart on those trade messages.send_chart(chart, start, end)sends one of a
Chartyou built, or withbroker=,symbol=andtimeframe=of a venue's
candles;send_photo(png)sends your own;send_report(report)sends a
backtest's figures, its balance curve and its HTML report.
Chart.screenshot(start, end, width=, height=, timezone=)makes them: a
headless Chromium photographs the chart's own page.
TraderConfig.chart_indicatorsputs indicators on a session's chart and its
pictures. - Price alerts —
bot.watch(broker, symbol, above=, below=, move_pct= with window=, on_close=, repeat=, rearm=, image=)returns anAlert: «🔔 BTCUSDT
crossed above 65,000 · now 65,012.5», with no strategy and no trading.
bot.alerts()lists them,alert.cancel()ends one, andbot.wait()keeps a
script alive until none is armed. - Commands from Telegram —
TelegramNotifier(..., commanders=[id])answers
/status,/positions,/chart,/stopand/help./stopends the
session as Ctrl+C does; live trading first asks for/stop CONFIRM, within
60 s. Commands sent while nothing listened are skipped, not run late, and
anyone not incommandersis refused. - Discord, e-mail and webhooks —
DiscordNotifierwithDiscordWebhook,
EmailNotifierwithEmailRecipient, andWebhookNotifierwith
WebhookTarget, each with its error (DiscordError,EmailError,
WebhookError). They take the same kinds, filters, templates, pictures and
queue, and work wherever a Telegram bot does. E-mail goes over SMTP with
STARTTLS or SSL and gathers a trade's messages into one e-mail every 15 minutes
(digest_minutes=0sends each at once). A webhook gets JSON with the text and
the event's raw fields, signed with HMAC-SHA256 when givensecret=. Discord
cannot reply, e-mail cannot edit, and commands stay Telegram's. [notify]extra (also as[telegram]) — PySocks for a SOCKS proxy and
Playwright for pictures, then, once,playwright install chromium. Text needs
nothing beyond the core install.- Runnable examples 04–09 — messages, paper trading's events, a chart
picture, price alerts and commands on Telegram, then Discord, e-mail and a
webhook. Each prints what to set when its variables are missing.
Changed
Chart.set_datais faster: it reads the frame by columns instead of
iterrows. A 300-candle chart took 0.29 s of CPU and now takes 7 ms.- The README's Event Log sample shows the lines the printer really prints, the
new events included.
Fixed
- Live trading skipped the first candle to close after a start. The seed
kept the candle that was still forming, so the feed's closed copy of it was
skipped as a repeat: that candle never reached the strategy, and its row kept
the values it had at the start.run_live,Traderand the Trader's
real-fills chart now seed with closed candles only, judged by the venue's
clock. examples/01_backtest_report.pynamed the wrong file in its docstring.
v1.1.1 — Bar replay: zones drawn up to the cursor
[1.1.1] — 2026-09-03
Bar replay: shapes that outlive the cursor.
Fixed
- A zone that ends in the future disappeared during replay. A box, trendline
or Fibonacci drawn from candle N to N+10 vanished from the chart until the
cursor passed N+10 — so a zone the trader could already see was missing for
exactly the candles it mattered on. Any shape running past the cursor is now
drawn up to the cursor: present, without giving away where it ends. Only
a position box's label is still blanked, because that announces the outcome. - Placing a shape used candles replay had not revealed. The chart is asked
where a moment sits on screen, and it only answers for candles the price
scale is currently showing. While replaying, the far edge of such a shape
lands on a hidden candle, so there was no answer — and no answer meant the
whole shape was dropped, which is what made it disappear entirely rather than
merely overshoot. Positions are now measured against the candles actually on
screen.
v1.1.0 — Charting: timeframes, multi-chart pages, bar replay
[1.1.0] — 2026-08-24
Charting. One set of candles in, any timeframe out, several charts at once, and
history you can step through.
Added
- Timeframe switching on the chart —
Chart(display_timeframe=…),
set_timeframe(),source_timeframe/timeframes, and a selector in the
toolbar. Feed 1m candles and display any whole multiple of them; resampling
and indicator maths run in Python, never in the browser. Only valid multiples
are offered, so4hdata never offers6h.
Indicators added by spec (chart_indicators, the toolbar) are recomputed
on the new candles; precomputed ones are thinned last-value-per-bucket and
flagged approximate, and their original points are restored when you switch
back. Streaming works through the conversion: 1m candles fed to a 5m display
grow the forming 5m candle and close it on its boundary. ChartPage— several charts on one page, on one port.page.add(chart)
stacks rows;page.add(chart, row=n)puts a chart beside the ones already
there, with dividers draggable on both axes. Charts scroll and crosshair
together by time, so different timeframes stay aligned. Attaching a chart
changes nothing about how you drive it — indicators, drawings, live positions,
streaming andset_timeframeall work unchanged.- Bar replay — pick a candle and step history forward or back, play at
0.25×–10×, withSpace/Shift+←/Shift+→/Esc. A step is one
source candle, so a 5m chart built from 1m data is watched being built.
Indicators stop at the last closed candle, while series that legitimately run
ahead of the data (Ichimoku's projected spans) keep that overhang. Backtest
positions never leak the future: a trade that has not opened is not drawn, and
one still open at the cursor stops there with no result label. On a
ChartPageone cursor drives every chart. resample_ohlcv(),detect_timeframe(),validate_conversion(),
can_convert()inAlgoTradeKit.data— the resampling maths as pure
functions, no files and no printing.Converternow delegates to them, so
there is one implementation.drop_incomplete=Falsekeeps the candle that is
still forming.- Runnable examples in
examples/, shipped with the package: a backtest with
its report, timeframe switching with bar replay, and a synchronised
multi-chart page. They fetch a little public Binance data with no API key and
fall back to synthetic candles offline. - A chart warns when its init payload runs to several megabytes, naming the
candle and drawing counts. Every viewer downloads and draws all of it, and a
ChartPagepays that once per chart in a single tab. Note that
candle_count_limiton a live session bounds the simulation window — the
report is recomputed over it — so use it deliberately. [mt5]extra inpyproject.toml.pip install AlgoTradeKit[mt5]has been
documented since v1.0.0 but never existed, so on Windows the native
MetaTrader path failed with an error telling you to install something pip
refused to install.
Fixed
- Report: the trade popup could not be used. Clicking a trade dot on the
balance chart opened a box with an "Open on Candle Chart" button that was
unreachable — hover handlers hid the box before the pointer arrived, and it
carriedpointer-events: nonebesides. A click now pins it; it closes on an
outside click,Esc, or its own ✕. The chart link also opened
127.0.0.1, which is the viewer's own machine when the report comes from a
VPS; it now uses the host the report was served from. - MetaTrader: a bridge that accepts the connection but never answers raised
a bareTimeoutErrorinstead of the guided error every other bridge failure
gives. It now names the likely causes and the guide section. MT5_WINE_SETUP.mdwas an earlier, shorter draft (Parts A–G). The Part
letters the connector's error messages point at were therefore wrong, and the
guide told you to install a Python version that does not work under Wine 9.- Chart servers leaked port reservations. Every
Chartcreated but never
shown held one for the life of the process, so building charts in a loop
eventually exhausted the port range. - Chart and report servers now shut down cleanly instead of stopping the
event loop under a running server, which raised out of the server thread.
v1.0.2 - trader module
[1.0.2] — 2026-07-24
Packaging fixes (no feature changes) — supersedes the withdrawn 1.0.0 and 1.0.1:
- 1.0.0 was built from an incomplete tree and shipped without the
tradermodule, the live-simulation core (simulate._live), the shared
position maths (simulate._position_math), incremental indicators
(strategy._incremental) and the MetaTrader native transport
(broker.metatrader._native/_ops), soimport AlgoTradeKit.traderfailed. - 1.0.1 restored that source but its source distribution accidentally
bundled repository-only files that do not belong in a release.
1.0.2 ships the complete library and nothing else: the source distribution
is now an explicit allow-list (src, tests, README, CHANGELOG, LICENSE,
MT5_WINE_SETUP.md, pyproject.toml). Upgrade with
pip install -U AlgoTradeKit.
v0.9.1 - broker module fix
[0.9.1] — 2026-07-01
Follow-up to the v0.9.0 broker module: a MetaTrader smoke-test demo, a
complete headless-setup guide, and a bridge fix for crypto / CFD symbols.
Added
MT5_WINE_SETUP.md— complete "MetaTrader 5 headless on a Linux VPS"
guide: install Wine + Xvfb, run the bridge server, open the SSH tunnel, plus a
troubleshooting table and optional systemd auto-start. Linked from the README.MetaTraderBroker.list_symbols(group="*BTC*")— discover a broker's exact
symbol spelling (they vary a lot between brokers).
Fixed
- MetaTrader bridge now calls
symbol_selectbefore everycopy_rates— crypto
/ CFD symbols are hidden from Market Watch by default and otherwise return no
candles.
v0.9.0 - broker module
[0.9.0] — 2026-07-01
Added
broker module — unified exchange & MetaTrader access (new)
Broker(name, ...)— one entry point for every venue.nameis
case-insensitive:"binance-spot","binance-futures","metatrader"
(aliasesmt5/forex). Credentials are optional — without them only
public market-data calls work; private (account / trading) calls raise a clear
AuthenticationError. Returns a concreteBaseBroker, so the whole library
treats every venue identically.BaseBrokerunified interface:fetch_candles/fetch_last_candles/
get_ticker/server_time,stream_candles/stream_ticker,
get_balance/get_account_info,create_order(+create_market_order/
create_limit_order),cancel_order/cancel_all,open_orders,
open_positions,close_position,set_leverage.- Unified types (
Balance,AccountInfo,Ticker,Order,OrderResult,
Position) and string constants (SIDE_BUY,ORDER_MARKET,MARKET_SPOT,
…) re-exported frombroker/__init__.py. - Binance connector (
broker/exchange/binance/): spot and USD-M futures.- REST: klines, ticker, server time; signed account, order create/cancel,
open orders, futures positions (positionRisk), balance,leverage.
Signing isHMAC-SHA256with the Python standard library — no new deps. - WebSocket: real-time
klineandbookTickerstreams, plus the private
user-data stream (auto listen-key keepalive). - Futures
create_ordercan attachstop_loss/take_profitas reduce-only
protective orders.testnet=Truepoints at Binance testnet.
- REST: klines, ticker, server time; signed account, order create/cancel,
- MetaTrader 5 connector (
broker/metatrader/) for headless Linux VPS:bridge_server.pyruns inside the Wine Python (whereMetaTrader5is
importable) underxvfb— no GUI. It exposes MT5 over a tiny
newline-delimited JSON socket (standard library only).MetaTraderBrokerruns on the normal Linux side and reaches MT5 only
through that bridge, mapping candles / positions / orders / account onto the
same unified types.MetaTrader5is never a dependency of AlgoTradeKit (it lives only in the
Wine Python), so there is no dependency conflict.
data module — now backed by broker
- All Binance REST kline logic moved into
broker;data.sources.binance
is now a thin adapter over it (public API unchanged). Collectoraccepts a name or aBrokerinstance — pass
Collector("binance-futures", …)(way 1, Collector builds the connector) or
Collector(my_broker, …)/Collector(..., broker=my_broker)(way 2, bring
your own — including an authenticated or MetaTrader forex connection).Collector.stream(on_candle)— real-time candle subscription for both
exchange (Binance WebSocket) and MetaTrader feeds.
Notes
- Live-order safety:
testnetis supported; live endpoints are the default. - Deferred to v0.9.1 (see
v091.md): thetraderlive-order module,
real-time simulation, live-updating chart/report, and the ichimoku live demo.
v0.8.0 - Indicator toolbar (add/edit) + chart_indicators
[0.8.0] — 2026-06-29
Added
visual module — working indicator toolbar (add / edit, backend-computed)
- Indicator button now works. The chart toolbar's INDICATORS button was
inert (it called an undefinedsendMsg); the panel now ships the chosen spec
to the backend over the WebSocket and the computed series returns as one or
moreadd_indicatormessages. The button (and its panel) were moved to the
left of the toolbar. - Edit existing indicators. Every indicator in the legend / oscillator pane
gains a ⚙ gear icon. Clicking it re-opens the panel pre-filled with that
indicator's current settings; saving recomputes it in the backend (the old
series is removed and replaced). Works for price-pane lines, the Ichimoku
group, and oscillator sub-panes (RSI / MACD / ATR). Chart.add_indicator_spec(params)— new public method that computes an
indicator from the chart's stored OHLCV server-side and tags each
resulting series with the resolvedspecthat produced it (so the front-end
gear can round-trip it). Used by both the toolbar andchart_indicators.- Ichimoku Displacement is now an editable parameter in the panel and in
indicator specs (defaults to 26). - Indicators added/edited live now survive a browser refresh (the server's
init-replay cache is kept in sync).
simulate module — indicators on the simulation chart
SimulateConfig.chart_indicators— new field: a list of indicator-spec
dicts (same schema as the toolbar) drawn on theshow_chart=Truecandle
chart. All maths run in the backend before the chart opens. Pass the
strategy's own indicator parameters to mirror what it traded on, add extra
indicators, or both. Validated in__post_init__(must be a list of dicts,
each with a"kind").
Fixed
- Ichimoku from the toolbar computed with the wrong argument order
(close, high, lowinstead ofhigh, low, close), producing incorrect
lines. Now correct and verified against a directIchimokucall. - RSI from the toolbar crashed on its default (
ma_type="none"→
None.upper()), and never showed its MA line becauseshow_mawas not set.
Both fixed. - VWAP / VWMA from the toolbar raised
TypeError: got multiple values for argument …due to mixed positional/keyword construction. Now built with
explicit keyword arguments.
Changed
ichimoku_strategy.pynow passeschart_indicatorsso the simulation chart
automatically renders the Ichimoku cloud + RSI (matching the strategy's
parameters, including the non-standard displacement).
v0.7.4 - Dynamic SL/TP lines, indicator toolbar, keep-alive fix
[0.7.4] — 2026-06-24
Added
simulate module — dynamic SL/TP visualisation
-
ClosedTrade.sl_history— newtuplefield recording every SL-state
change throughout a trade's lifetime as an ordered sequence of dicts
{"time": int_ms, "sl": float, "next_tp": float | None}. An entry is
appended at position open (initial state) and again every time the SL
advances: after eachmulti_rrTP level hit (SL walks to break-even /
previous TP) or whenever the trailing SL moves to a new high-water mark.
An empty history means the SL never moved; a single entry means the
position opened but the SL never advanced before closing. -
ClosedTrade.final_next_tp— newfloat | Nonefield that records
the TP target that was active at the exact moment the trade closed. For
amulti_rrposition that hit TP3 (moving next target to TP4) and was
then stopped out at the TP3-advanced SL, this is TP4.Nonewhen all
levels were consumed (position closed at the final TP) or no TP was
configured. -
ClosedTrade.peak_price— newfloatfield storing the most
favourable price reached during the trade (highest high for longs, lowest
low for shorts). Used by the visual module as the top of the position box
for trailing-SL trades (the peak marks the last price that drove the
trailing SL to its tightest level). -
SimulateReport.trade_markersnow includessl_history,final_next_tp,
peak_price, andrr_levels_hitfor every marker, enabling the
chart-side rendering of dynamic SL/TP lines.
visual module — dynamic SL/TP lines on chart
-
add_simulation_positions(inindicator_renderer.py) enhanced with:- Dynamic SL line segments — for
multi_rrandtrailingpositions,
coloured horizontalTrendLinedrawings are added alongside each position
box showing where the stop-loss was at each stage of the trade:- Red — SL is in the loss zone (below entry for long)
- Amber/yellow — SL is at break-even (entry price)
- Cyan — SL is in profit territory (above entry for long)
- Green TP lines (
multi_rronly) — for each SL segment, a matching
green horizontal line shows the next TP target that was being aimed at. - Posbox TP fix — the profit-zone boundary of the position box now
showsfinal_next_tp(the TP at closing time) rather than the initial
TP at entry. After hitting TP3 with next target TP4, the box correctly
displays TP4 instead of staying stuck at TP1. - Trailing posbox top — for
sl_mode="trailing", the top of the
position box is set topeak_price(the highest price the trailing SL
ever chased), giving a natural view of the profit zone that was available. - Partial-close grouping — multiple
ClosedTraderows sharing a
trade_id(fromtp_level_close_fractions) are now collapsed into a
single position box (one box per unique trade, not one per slice). - New
configparameter onadd_simulation_positions— pass the
SimulateConfigused for the simulation to enable automatic mode
detection (tp_mode/sl_mode) for the correct line style.
- Dynamic SL line segments — for
-
Indicator toolbar — a new 📈 button in the chart toolbar opens an
"Add Indicator" panel where the user can add technical indicators to the
live candle chart without writing any code:- Moving averages: EMA, SMA, WMA, SMMA, DEMA, TEMA, HMA, VWMA, VWAP
- Oscillators: RSI (with optional MA), MACD, ATR (pure Python — no
third-party TA library) - Trend: Ichimoku Cloud
- Each indicator type shows its own parameter form (period, source, MA
type, fast/slow/signal periods, Tenkan/Kijun/Senkou B, etc.). - A colour picker lets the user override the default series colour.
- The "Add to Chart" button sends a
compute_indicatorWebSocket message
to theChartserver, which computes the indicator from the stored OHLCV
DataFrameand broadcasts the result as one or moreadd_indicator
messages; the chart renders them immediately.
Fixed
-
Trailing SL false gap-open trigger — the trailing SL was previously
advanced in step A (before close checks), which could cause a "gap open
past SL" close on the very candle that caused the SL to jump, when the
candle's open price was between the old and new SL levels. The trailing
SL is now advanced inside_check_closeafter the gap-open test, so
the gap check always uses the SL from the end of the previous candle.
This fix applies to both the single-pairSimulateengine and the
multi-pairrun_multiengine (_runner.py). -
Chart and report tabs disconnecting immediately — the
ChartServerandReportServerboth run in daemon threads, which Python
kills the instant the script's main thread exits. Previously,
Simulate.run()started both servers non-blocking and returned, so all
user code after the call (printing stats, saving CSV history, etc.) ran
normally — but as soon asmain()returned the process died, closing both
browser tabs before the user could interact with them. A one-timeatexit
handler is now registered whenever a browser UI is opened; it blocks with
awhile True: sleep(1)loop (identical tochart.show(block=True)) after
all user code has finished, keeping the process alive until the user presses
Ctrl+C. The handler registers only once per process invocation, so
multipleSimulate.run()calls (batch/multi-symbol) produce a single
blocking handler at exit.
Tests
tests/test_simulate.py— newTestSlHistoryclass (13 tests) covering:sl_historylength and content after 0, 1, and 2multi_rrTP hits- timestamp presence and ordering in
sl_history final_next_tpvalue after partial and final TP consumptionpeak_pricecaptured correctly for trailing-SL trades- backward-compatibility: plain
signalSL mode produces exactly one
sl_historyentry (no SL movement) add_simulation_positionssmoke test: one posbox per uniquetrade_id- dynamic SL
TrendLinedrawings added whensl_historylength > 1 - posbox
take_profitusesfinal_next_tpnot initial TP
v0.7.3 - Per-signal position sizing and partial multi-RR take-profit closes
[0.7.3] — 2026-06-21
Added
strategy module
Signal.risk_multiplier— new optional field (default1.0) that scales
the size/risk a single signal receives relative to the run's global
SimulateConfigsizing (risk_percent/fixed_amount/fixed_lot).
Lets a strategy vary risk per signal instead of using one fixed sizing
rule for every trade in a backtest — e.g. half size on a tentative
"limit" entry vs. full size on a confirmed one, or splitting one trade
idea into several sub-positions whose sizes sum to one risk unit
(three signals at1/3each, targeting 1R/2R/3R, to emulate scaling out
of a position). Default1.0is fully backward compatible.
simulate module
-
SimulateConfig.tp_level_close_fractions— optional list, parallel to
tp_levels, that turns on true partial closes fortp_mode="multi_rr".
Each entry is the fraction of the position's original size to realise
when the corresponding level is reached, instead of only moving the SL.
None(default) preserves the exact pre-0.7.3 behaviour (SL-only
advancement, single full close at the final level). When set:- fractions summing to
1.0give a full progressive scale-out
(e.g.[1/3, 1/3, 1/3]) — profit is banked level by level instead of
all-or-nothing at the end. - all-zero fractions give a "let it run" position: the SL just walks
through every level and the full size stays open, trailing at the
last level's price, until eventually stopped out. - any mix is valid — partially bank some levels, let others purely
advance the SL.
Each partial close produces its own
ClosedTradesharing the position's
trade_id, soSimulateReportstatistics (win rate, profit factor,
equity curve) count every realised slice on its own line, the same way
a real scaled-out position would appear on a broker statement.
Commission (pre-charged once, in full, at entry) is split proportionally
across every slice so the total charged across one position's full
lifetime never changes. - fractions summing to
-
CLOSE_REASON_TP_PARTIALis now exported fromAlgoTradeKit.simulate.
It existed onClosedTradesince an earlier release (withis_tp
already wired to recognise it) but no code path had ever produced it
untiltp_level_close_fractionsabove. -
run_multi()gained the identical partial-close handling as the
single-pairSimulateengine, so shared-wallet multi-symbol portfolios
behave the same way;run_batch()needed no changes (it only wraps
Simulate(cfg).run()).
Tests
tests/test_strategy.py—TestSignalextended with 5 tests for
risk_multiplier(default, custom value,<= 0validation, positional-
construction backward compatibility).tests/test_simulate.py— newTestEngineRiskMultiplier(4 tests) and
TestEngineMultiRRPartialClose(8 tests, including a hand-derived PnL
ground truth and an end-to-end wallet-conservation check) and
TestSimulateConfigPartialTPValidation(8 tests). All 171 pre-existing
tests in these two files continue to pass unmodified.
v0.7.2 - Normalizer, ATR indicator, Ichimoku raw spans, Chart candle range
[0.7.2] — 2026-06-20
Added
data module
Normalizer— new class to ingest non-standard OHLCV CSV files and
convert them to the AlgoTradeKit standard format. Features:- Auto-detects whether timestamps are in Unix seconds (
< 10^10) or
milliseconds (≥ 10^10) and converts to ms automatically. - Fills missing optional columns (
close_time,quote_volume,trades,
taker_buy_base,taker_buy_quote) withNone;volumedefaults to0. - Date-range filtering via
start/endattributes before returning data
(integers are also auto-detected as seconds or ms). - Three usage modes:
normalize()→ DataFrame,save()→ CSV path,
normalize_and_save()→(DataFrame, path). Normalizeris now exported fromAlgoTradeKit.data.
- Auto-detects whether timestamps are in Unix seconds (
indicator module
ATR— Average True Range using Wilder's RMA smoothing (alpha = 1 / period,
min_periods = period). Matches TradingViewta.atr()output.
Exposesatrandtrproperties and result-dict keys.
Default period: 14. Exported fromAlgoTradeKit.indicator.Ichimoku.span_a_rawandIchimoku.span_b_raw— two new properties
(andresultdict keys) exposing the unshifted Senkou Span A and B values
at each bar (i.e.(tenkan + kijun) / 2and the Span B donchian mid before
the displacement shift is applied). These are required for strategy entry/exit
logic where the current cloud position matters, not the displayed future cloud.
Fully backward-compatible — no existing keys or properties were changed.
visual module
-
Chart.set_data(candle_range=...)— new optionalcandle_rangedict
parameter filters which candles are rendered. Five modes:{"start": ..., "end": ...}— inclusive datetime range (either key optional){"start": ...}— from date to the last available candle{"end": ...}— from the first candle to date{"last_n": N}— last N candles{"first_n": N}— first N candles
start/endaccept"YYYY/MM/DD","YYYY-MM-DD"strings,datetime
objects, Unix-secondint, or Unix-millisecondint. -
Chart.from_csv(candle_range=...)—candle_rangeforwarded from the
factory class method.
Tests
tests/test_data_normalizer.py— 25+ unit tests forNormalizercovering
timestamp detection, date filtering, schema completeness, save/load round-trip,
and error paths.tests/test_indicator.py— extended withTestATR(15 tests) and
TestIchimokuRawSpans(10 tests) for the new indicator features.