TradeChart 2.4.0__tar.gz → 2.5.0__tar.gz
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.
- {tradechart-2.4.0 → tradechart-2.5.0}/PKG-INFO +20 -16
- {tradechart-2.4.0 → tradechart-2.5.0}/README.md +18 -14
- {tradechart-2.4.0 → tradechart-2.5.0}/TradeChart.egg-info/PKG-INFO +20 -16
- {tradechart-2.4.0 → tradechart-2.5.0}/pyproject.toml +2 -2
- {tradechart-2.4.0 → tradechart-2.5.0}/tradechart/__init__.py +7 -1
- tradechart-2.5.0/tradechart/charts/__init__.py +11 -0
- {tradechart-2.4.0 → tradechart-2.5.0}/tradechart/charts/heatmap.py +41 -34
- tradechart-2.5.0/tradechart/charts/renderer.py +933 -0
- {tradechart-2.4.0 → tradechart-2.5.0}/tradechart/charts/themes.py +32 -24
- {tradechart-2.4.0 → tradechart-2.5.0}/tradechart/charts/watermark.py +10 -5
- {tradechart-2.4.0 → tradechart-2.5.0}/tradechart/config/settings.py +60 -0
- {tradechart-2.4.0 → tradechart-2.5.0}/tradechart/core/engine.py +45 -47
- tradechart-2.4.0/tradechart/charts/__init__.py +0 -8
- tradechart-2.4.0/tradechart/charts/renderer.py +0 -460
- {tradechart-2.4.0 → tradechart-2.5.0}/LICENSE +0 -0
- {tradechart-2.4.0 → tradechart-2.5.0}/TradeChart.egg-info/SOURCES.txt +0 -0
- {tradechart-2.4.0 → tradechart-2.5.0}/TradeChart.egg-info/dependency_links.txt +0 -0
- {tradechart-2.4.0 → tradechart-2.5.0}/TradeChart.egg-info/requires.txt +0 -0
- {tradechart-2.4.0 → tradechart-2.5.0}/TradeChart.egg-info/top_level.txt +0 -0
- {tradechart-2.4.0 → tradechart-2.5.0}/setup.cfg +0 -0
- {tradechart-2.4.0 → tradechart-2.5.0}/tradechart/charts/indicators.py +0 -0
- {tradechart-2.4.0 → tradechart-2.5.0}/tradechart/config/__init__.py +0 -0
- {tradechart-2.4.0 → tradechart-2.5.0}/tradechart/config/logger.py +0 -0
- {tradechart-2.4.0 → tradechart-2.5.0}/tradechart/core/__init__.py +0 -0
- {tradechart-2.4.0 → tradechart-2.5.0}/tradechart/data/__init__.py +0 -0
- {tradechart-2.4.0 → tradechart-2.5.0}/tradechart/data/fetcher.py +0 -0
- {tradechart-2.4.0 → tradechart-2.5.0}/tradechart/data/groups.py +0 -0
- {tradechart-2.4.0 → tradechart-2.5.0}/tradechart/data/models.py +0 -0
- {tradechart-2.4.0 → tradechart-2.5.0}/tradechart/data/provider_base.py +0 -0
- {tradechart-2.4.0 → tradechart-2.5.0}/tradechart/data/store.py +0 -0
- {tradechart-2.4.0 → tradechart-2.5.0}/tradechart/providers/__init__.py +0 -0
- {tradechart-2.4.0 → tradechart-2.5.0}/tradechart/providers/stooq_provider.py +0 -0
- {tradechart-2.4.0 → tradechart-2.5.0}/tradechart/providers/tradingview_provider.py +0 -0
- {tradechart-2.4.0 → tradechart-2.5.0}/tradechart/providers/yfinance_provider.py +0 -0
- {tradechart-2.4.0 → tradechart-2.5.0}/tradechart/utils/__init__.py +0 -0
- {tradechart-2.4.0 → tradechart-2.5.0}/tradechart/utils/exceptions.py +0 -0
- {tradechart-2.4.0 → tradechart-2.5.0}/tradechart/utils/formatting.py +0 -0
- {tradechart-2.4.0 → tradechart-2.5.0}/tradechart/utils/install.py +0 -0
- {tradechart-2.4.0 → tradechart-2.5.0}/tradechart/utils/validation.py +0 -0
- {tradechart-2.4.0 → tradechart-2.5.0}/tradechart_examples/discord_demo_bot/discord_bot.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: TradeChart
|
|
3
|
-
Version: 2.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 2.5.0
|
|
4
|
+
Summary: Sleek financial charts from Python — candlestick, line, area, OHLC, Heikin-Ashi, and performance heatmaps.
|
|
5
5
|
Author-email: "TRADELY.DEV" <dev@tradely.dev>
|
|
6
6
|
License: Apache-2.0
|
|
7
7
|
Project-URL: Homepage, https://github.com/techareaone/TradeChart
|
|
@@ -45,7 +45,7 @@ Requires-Dist: build>=1.0; extra == "dev"
|
|
|
45
45
|
Requires-Dist: twine>=5.0; extra == "dev"
|
|
46
46
|
Dynamic: license-file
|
|
47
47
|
|
|
48
|
-
# TradeChart — Library Edition v2.
|
|
48
|
+
# TradeChart — Library Edition v2.5.0
|
|
49
49
|
|
|
50
50
|
**Python → Financial Charts**
|
|
51
51
|
Generate production-quality candlestick, line, area, OHLC, Heikin-Ashi, and performance heatmap charts from code.
|
|
@@ -64,7 +64,7 @@ pip install TradeChart
|
|
|
64
64
|
| Extra | Installs | Benefit |
|
|
65
65
|
|---|---|---|
|
|
66
66
|
| `TradeChart[tradingview]` | `tvDatafeed` | TradingView as a fallback data provider |
|
|
67
|
-
| `TradeChart[mplfinance]` | `mplfinance` |
|
|
67
|
+
| `TradeChart[mplfinance]` | `mplfinance` | Optional candlestick backend. The default engine is native. Opt in with `tc.config(engine="mplfinance")`. |
|
|
68
68
|
| `TradeChart[xlsx]` | `openpyxl` | Excel `.xlsx` export support |
|
|
69
69
|
| `TradeChart[all]` | All of the above | Everything |
|
|
70
70
|
|
|
@@ -453,6 +453,8 @@ tc.config(
|
|
|
453
453
|
| `dpi` | `int` | `100` | `50`–`600` | Output resolution in dots per inch. Higher values produce larger, sharper files. |
|
|
454
454
|
| `fig_size` | `tuple[int, int]` | `(12, 6)` | Any valid `(width, height)` in inches | Matplotlib figure size. Increase for wide monitors or presentations. |
|
|
455
455
|
| `cache_ttl` | `int` | `300` | Any positive integer (seconds) | How long fetched data is kept in memory. `0` effectively disables caching. |
|
|
456
|
+
| `engine` | `str` | `"native"` | `"native"`, `"mplfinance"` | Drawing entry point. `"native"` is the default sleek engine. `"mplfinance"` keeps the optional candlestick backend for `"candle"` and `"heikin_ashi"`. |
|
|
457
|
+
| `font` | `str` | `"sans"` | `"sans"`, `"serif"`, `"mono"` | Typeface. `"sans"` is sans-serif and is used when this is omitted. `"serif"` and `"mono"` are the other built-in choices. |
|
|
456
458
|
|
|
457
459
|
---
|
|
458
460
|
|
|
@@ -486,9 +488,9 @@ tc.theme("classic")
|
|
|
486
488
|
|
|
487
489
|
| Name | Background | Candle colours | Spine |
|
|
488
490
|
|---|---|---|---|
|
|
489
|
-
| `"dark"` | `#
|
|
490
|
-
| `"light"` | `#
|
|
491
|
-
| `"classic"` | `#
|
|
491
|
+
| `"dark"` | `#0e1117` | Green `#3dd68c` / Red `#f07178` | Hidden |
|
|
492
|
+
| `"light"` | `#f4f6f8` | Green `#1a9f6b` / Red `#e24b4b` | Hidden |
|
|
493
|
+
| `"classic"` | `#f3efe2` (parchment) | Green `#1f7a3a` / Red `#a32020` | Visible |
|
|
492
494
|
|
|
493
495
|
---
|
|
494
496
|
|
|
@@ -598,11 +600,19 @@ The global settings singleton and engine initialisation are protected by locks.
|
|
|
598
600
|
**Heikin-Ashi**
|
|
599
601
|
The `"heikin_ashi"` chart type converts standard OHLC data to Heikin-Ashi candles during rendering only. The cached source data and any DataFrame returned by `tc.data()` are never modified.
|
|
600
602
|
|
|
601
|
-
**
|
|
602
|
-
|
|
603
|
+
**Rendering**
|
|
604
|
+
`tc.chart()`, `tc.compare()`, and `tc.heatmap()` draw through the native engine (`render_chart`, `render_comparison`, and the heatmap renderer). Candles are two vector collections — one for wicks, one for bodies — the figure is positioned once, and the file is written in a single pass. That is lighter than a general-purpose chart stack, and it is the look in the examples below.
|
|
605
|
+
|
|
606
|
+
`mplfinance` is still supported. Install `TradeChart[mplfinance]` and select it when you want that backend for candlestick and Heikin-Ashi charts:
|
|
607
|
+
|
|
608
|
+
```python
|
|
609
|
+
tc.config(engine="mplfinance")
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
Line, area, OHLC, comparison, and heatmap charts stay on the native engine. Required dependencies are unchanged: `matplotlib`, `pandas`, `numpy`, and `yfinance`. `tvDatafeed`, `mplfinance`, and `openpyxl` remain optional extras.
|
|
603
613
|
|
|
604
614
|
**Output resolution**
|
|
605
|
-
Default DPI is 100, producing a ~1200 × 600 px image at the default figure size
|
|
615
|
+
Default DPI is 100, producing a ~1200 × 600 px image at the default figure size. Increase with `tc.config(dpi=200)` for sharper output, or `tc.config(dpi=300)` for print quality.
|
|
606
616
|
|
|
607
617
|
---
|
|
608
618
|
|
|
@@ -632,12 +642,6 @@ except RenderError as e:
|
|
|
632
642
|
|
|
633
643
|
---
|
|
634
644
|
|
|
635
|
-
## Example Charts
|
|
636
|
-
<img width="2081" height="1039" alt="image" src="https://github.com/user-attachments/assets/b93f79e6-a135-4de8-993d-ee13071fe791" />
|
|
637
|
-
<img width="2081" height="1039" alt="image" src="https://github.com/user-attachments/assets/b0755b35-b21c-4b27-8faa-c57e13892dad" />
|
|
638
|
-
|
|
639
|
-
---
|
|
640
|
-
|
|
641
645
|
## Further Details
|
|
642
646
|
|
|
643
647
|
- Documentation: [doc.tradely.dev](https://doc.tradely.dev)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# TradeChart — Library Edition v2.
|
|
1
|
+
# TradeChart — Library Edition v2.5.0
|
|
2
2
|
|
|
3
3
|
**Python → Financial Charts**
|
|
4
4
|
Generate production-quality candlestick, line, area, OHLC, Heikin-Ashi, and performance heatmap charts from code.
|
|
@@ -17,7 +17,7 @@ pip install TradeChart
|
|
|
17
17
|
| Extra | Installs | Benefit |
|
|
18
18
|
|---|---|---|
|
|
19
19
|
| `TradeChart[tradingview]` | `tvDatafeed` | TradingView as a fallback data provider |
|
|
20
|
-
| `TradeChart[mplfinance]` | `mplfinance` |
|
|
20
|
+
| `TradeChart[mplfinance]` | `mplfinance` | Optional candlestick backend. The default engine is native. Opt in with `tc.config(engine="mplfinance")`. |
|
|
21
21
|
| `TradeChart[xlsx]` | `openpyxl` | Excel `.xlsx` export support |
|
|
22
22
|
| `TradeChart[all]` | All of the above | Everything |
|
|
23
23
|
|
|
@@ -406,6 +406,8 @@ tc.config(
|
|
|
406
406
|
| `dpi` | `int` | `100` | `50`–`600` | Output resolution in dots per inch. Higher values produce larger, sharper files. |
|
|
407
407
|
| `fig_size` | `tuple[int, int]` | `(12, 6)` | Any valid `(width, height)` in inches | Matplotlib figure size. Increase for wide monitors or presentations. |
|
|
408
408
|
| `cache_ttl` | `int` | `300` | Any positive integer (seconds) | How long fetched data is kept in memory. `0` effectively disables caching. |
|
|
409
|
+
| `engine` | `str` | `"native"` | `"native"`, `"mplfinance"` | Drawing entry point. `"native"` is the default sleek engine. `"mplfinance"` keeps the optional candlestick backend for `"candle"` and `"heikin_ashi"`. |
|
|
410
|
+
| `font` | `str` | `"sans"` | `"sans"`, `"serif"`, `"mono"` | Typeface. `"sans"` is sans-serif and is used when this is omitted. `"serif"` and `"mono"` are the other built-in choices. |
|
|
409
411
|
|
|
410
412
|
---
|
|
411
413
|
|
|
@@ -439,9 +441,9 @@ tc.theme("classic")
|
|
|
439
441
|
|
|
440
442
|
| Name | Background | Candle colours | Spine |
|
|
441
443
|
|---|---|---|---|
|
|
442
|
-
| `"dark"` | `#
|
|
443
|
-
| `"light"` | `#
|
|
444
|
-
| `"classic"` | `#
|
|
444
|
+
| `"dark"` | `#0e1117` | Green `#3dd68c` / Red `#f07178` | Hidden |
|
|
445
|
+
| `"light"` | `#f4f6f8` | Green `#1a9f6b` / Red `#e24b4b` | Hidden |
|
|
446
|
+
| `"classic"` | `#f3efe2` (parchment) | Green `#1f7a3a` / Red `#a32020` | Visible |
|
|
445
447
|
|
|
446
448
|
---
|
|
447
449
|
|
|
@@ -551,11 +553,19 @@ The global settings singleton and engine initialisation are protected by locks.
|
|
|
551
553
|
**Heikin-Ashi**
|
|
552
554
|
The `"heikin_ashi"` chart type converts standard OHLC data to Heikin-Ashi candles during rendering only. The cached source data and any DataFrame returned by `tc.data()` are never modified.
|
|
553
555
|
|
|
554
|
-
**
|
|
555
|
-
|
|
556
|
+
**Rendering**
|
|
557
|
+
`tc.chart()`, `tc.compare()`, and `tc.heatmap()` draw through the native engine (`render_chart`, `render_comparison`, and the heatmap renderer). Candles are two vector collections — one for wicks, one for bodies — the figure is positioned once, and the file is written in a single pass. That is lighter than a general-purpose chart stack, and it is the look in the examples below.
|
|
558
|
+
|
|
559
|
+
`mplfinance` is still supported. Install `TradeChart[mplfinance]` and select it when you want that backend for candlestick and Heikin-Ashi charts:
|
|
560
|
+
|
|
561
|
+
```python
|
|
562
|
+
tc.config(engine="mplfinance")
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
Line, area, OHLC, comparison, and heatmap charts stay on the native engine. Required dependencies are unchanged: `matplotlib`, `pandas`, `numpy`, and `yfinance`. `tvDatafeed`, `mplfinance`, and `openpyxl` remain optional extras.
|
|
556
566
|
|
|
557
567
|
**Output resolution**
|
|
558
|
-
Default DPI is 100, producing a ~1200 × 600 px image at the default figure size
|
|
568
|
+
Default DPI is 100, producing a ~1200 × 600 px image at the default figure size. Increase with `tc.config(dpi=200)` for sharper output, or `tc.config(dpi=300)` for print quality.
|
|
559
569
|
|
|
560
570
|
---
|
|
561
571
|
|
|
@@ -585,12 +595,6 @@ except RenderError as e:
|
|
|
585
595
|
|
|
586
596
|
---
|
|
587
597
|
|
|
588
|
-
## Example Charts
|
|
589
|
-
<img width="2081" height="1039" alt="image" src="https://github.com/user-attachments/assets/b93f79e6-a135-4de8-993d-ee13071fe791" />
|
|
590
|
-
<img width="2081" height="1039" alt="image" src="https://github.com/user-attachments/assets/b0755b35-b21c-4b27-8faa-c57e13892dad" />
|
|
591
|
-
|
|
592
|
-
---
|
|
593
|
-
|
|
594
598
|
## Further Details
|
|
595
599
|
|
|
596
600
|
- Documentation: [doc.tradely.dev](https://doc.tradely.dev)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: TradeChart
|
|
3
|
-
Version: 2.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 2.5.0
|
|
4
|
+
Summary: Sleek financial charts from Python — candlestick, line, area, OHLC, Heikin-Ashi, and performance heatmaps.
|
|
5
5
|
Author-email: "TRADELY.DEV" <dev@tradely.dev>
|
|
6
6
|
License: Apache-2.0
|
|
7
7
|
Project-URL: Homepage, https://github.com/techareaone/TradeChart
|
|
@@ -45,7 +45,7 @@ Requires-Dist: build>=1.0; extra == "dev"
|
|
|
45
45
|
Requires-Dist: twine>=5.0; extra == "dev"
|
|
46
46
|
Dynamic: license-file
|
|
47
47
|
|
|
48
|
-
# TradeChart — Library Edition v2.
|
|
48
|
+
# TradeChart — Library Edition v2.5.0
|
|
49
49
|
|
|
50
50
|
**Python → Financial Charts**
|
|
51
51
|
Generate production-quality candlestick, line, area, OHLC, Heikin-Ashi, and performance heatmap charts from code.
|
|
@@ -64,7 +64,7 @@ pip install TradeChart
|
|
|
64
64
|
| Extra | Installs | Benefit |
|
|
65
65
|
|---|---|---|
|
|
66
66
|
| `TradeChart[tradingview]` | `tvDatafeed` | TradingView as a fallback data provider |
|
|
67
|
-
| `TradeChart[mplfinance]` | `mplfinance` |
|
|
67
|
+
| `TradeChart[mplfinance]` | `mplfinance` | Optional candlestick backend. The default engine is native. Opt in with `tc.config(engine="mplfinance")`. |
|
|
68
68
|
| `TradeChart[xlsx]` | `openpyxl` | Excel `.xlsx` export support |
|
|
69
69
|
| `TradeChart[all]` | All of the above | Everything |
|
|
70
70
|
|
|
@@ -453,6 +453,8 @@ tc.config(
|
|
|
453
453
|
| `dpi` | `int` | `100` | `50`–`600` | Output resolution in dots per inch. Higher values produce larger, sharper files. |
|
|
454
454
|
| `fig_size` | `tuple[int, int]` | `(12, 6)` | Any valid `(width, height)` in inches | Matplotlib figure size. Increase for wide monitors or presentations. |
|
|
455
455
|
| `cache_ttl` | `int` | `300` | Any positive integer (seconds) | How long fetched data is kept in memory. `0` effectively disables caching. |
|
|
456
|
+
| `engine` | `str` | `"native"` | `"native"`, `"mplfinance"` | Drawing entry point. `"native"` is the default sleek engine. `"mplfinance"` keeps the optional candlestick backend for `"candle"` and `"heikin_ashi"`. |
|
|
457
|
+
| `font` | `str` | `"sans"` | `"sans"`, `"serif"`, `"mono"` | Typeface. `"sans"` is sans-serif and is used when this is omitted. `"serif"` and `"mono"` are the other built-in choices. |
|
|
456
458
|
|
|
457
459
|
---
|
|
458
460
|
|
|
@@ -486,9 +488,9 @@ tc.theme("classic")
|
|
|
486
488
|
|
|
487
489
|
| Name | Background | Candle colours | Spine |
|
|
488
490
|
|---|---|---|---|
|
|
489
|
-
| `"dark"` | `#
|
|
490
|
-
| `"light"` | `#
|
|
491
|
-
| `"classic"` | `#
|
|
491
|
+
| `"dark"` | `#0e1117` | Green `#3dd68c` / Red `#f07178` | Hidden |
|
|
492
|
+
| `"light"` | `#f4f6f8` | Green `#1a9f6b` / Red `#e24b4b` | Hidden |
|
|
493
|
+
| `"classic"` | `#f3efe2` (parchment) | Green `#1f7a3a` / Red `#a32020` | Visible |
|
|
492
494
|
|
|
493
495
|
---
|
|
494
496
|
|
|
@@ -598,11 +600,19 @@ The global settings singleton and engine initialisation are protected by locks.
|
|
|
598
600
|
**Heikin-Ashi**
|
|
599
601
|
The `"heikin_ashi"` chart type converts standard OHLC data to Heikin-Ashi candles during rendering only. The cached source data and any DataFrame returned by `tc.data()` are never modified.
|
|
600
602
|
|
|
601
|
-
**
|
|
602
|
-
|
|
603
|
+
**Rendering**
|
|
604
|
+
`tc.chart()`, `tc.compare()`, and `tc.heatmap()` draw through the native engine (`render_chart`, `render_comparison`, and the heatmap renderer). Candles are two vector collections — one for wicks, one for bodies — the figure is positioned once, and the file is written in a single pass. That is lighter than a general-purpose chart stack, and it is the look in the examples below.
|
|
605
|
+
|
|
606
|
+
`mplfinance` is still supported. Install `TradeChart[mplfinance]` and select it when you want that backend for candlestick and Heikin-Ashi charts:
|
|
607
|
+
|
|
608
|
+
```python
|
|
609
|
+
tc.config(engine="mplfinance")
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
Line, area, OHLC, comparison, and heatmap charts stay on the native engine. Required dependencies are unchanged: `matplotlib`, `pandas`, `numpy`, and `yfinance`. `tvDatafeed`, `mplfinance`, and `openpyxl` remain optional extras.
|
|
603
613
|
|
|
604
614
|
**Output resolution**
|
|
605
|
-
Default DPI is 100, producing a ~1200 × 600 px image at the default figure size
|
|
615
|
+
Default DPI is 100, producing a ~1200 × 600 px image at the default figure size. Increase with `tc.config(dpi=200)` for sharper output, or `tc.config(dpi=300)` for print quality.
|
|
606
616
|
|
|
607
617
|
---
|
|
608
618
|
|
|
@@ -632,12 +642,6 @@ except RenderError as e:
|
|
|
632
642
|
|
|
633
643
|
---
|
|
634
644
|
|
|
635
|
-
## Example Charts
|
|
636
|
-
<img width="2081" height="1039" alt="image" src="https://github.com/user-attachments/assets/b93f79e6-a135-4de8-993d-ee13071fe791" />
|
|
637
|
-
<img width="2081" height="1039" alt="image" src="https://github.com/user-attachments/assets/b0755b35-b21c-4b27-8faa-c57e13892dad" />
|
|
638
|
-
|
|
639
|
-
---
|
|
640
|
-
|
|
641
645
|
## Further Details
|
|
642
646
|
|
|
643
647
|
- Documentation: [doc.tradely.dev](https://doc.tradely.dev)
|
|
@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "TradeChart"
|
|
7
|
-
version = "2.
|
|
8
|
-
description = "
|
|
7
|
+
version = "2.5.0"
|
|
8
|
+
description = "Sleek financial charts from Python — candlestick, line, area, OHLC, Heikin-Ashi, and performance heatmaps."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "Apache-2.0"}
|
|
11
11
|
requires-python = ">=3.10"
|
|
@@ -87,7 +87,7 @@ from tradechart.utils.exceptions import (
|
|
|
87
87
|
)
|
|
88
88
|
from tradechart.utils.validation import VALID_DURATIONS
|
|
89
89
|
|
|
90
|
-
__version__ = "2.
|
|
90
|
+
__version__ = "2.5.0"
|
|
91
91
|
__all__ = [
|
|
92
92
|
"terminal", "theme", "watermark", "config",
|
|
93
93
|
"chart", "compare", "heatmap", "data", "export", "clear_cache",
|
|
@@ -153,6 +153,8 @@ def config(**kwargs) -> dict:
|
|
|
153
153
|
dpi : int — output resolution (50–600)
|
|
154
154
|
fig_size : tuple[int,int] — figure dimensions in inches
|
|
155
155
|
cache_ttl : int — data cache time-to-live in seconds
|
|
156
|
+
engine : str — ``"native"`` (default) or ``"mplfinance"``
|
|
157
|
+
font : str — ``"sans"`` (default), ``"serif"``, or ``"mono"``
|
|
156
158
|
|
|
157
159
|
Example
|
|
158
160
|
-------
|
|
@@ -167,6 +169,8 @@ def config(**kwargs) -> dict:
|
|
|
167
169
|
"dpi": lambda v: setattr(s, "dpi", v),
|
|
168
170
|
"fig_size": lambda v: setattr(s, "fig_size", v),
|
|
169
171
|
"cache_ttl": lambda v: setattr(s, "cache_ttl", v),
|
|
172
|
+
"engine": lambda v: setattr(s, "chart_engine", v),
|
|
173
|
+
"font": lambda v: setattr(s, "font", v),
|
|
170
174
|
}
|
|
171
175
|
for key, value in kwargs.items():
|
|
172
176
|
setter = dispatch.get(key)
|
|
@@ -185,6 +189,8 @@ def config(**kwargs) -> dict:
|
|
|
185
189
|
"dpi": s.dpi,
|
|
186
190
|
"fig_size": s.fig_size,
|
|
187
191
|
"cache_ttl": s.cache_ttl,
|
|
192
|
+
"engine": s.chart_engine,
|
|
193
|
+
"font": s.font,
|
|
188
194
|
}
|
|
189
195
|
|
|
190
196
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""Chart rendering layer."""
|
|
2
|
+
|
|
3
|
+
from tradechart.charts.renderer import ChartRenderer, render_chart, render_comparison
|
|
4
|
+
from tradechart.charts.watermark import stamp_logo, clear_cache as clear_logo_cache
|
|
5
|
+
from tradechart.charts.themes import Theme, get_theme
|
|
6
|
+
from tradechart.charts.indicators import apply_indicators
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"ChartRenderer", "render_chart", "render_comparison",
|
|
10
|
+
"stamp_logo", "clear_logo_cache", "Theme", "get_theme", "apply_indicators",
|
|
11
|
+
]
|
|
@@ -21,6 +21,7 @@ import matplotlib.patches as mpatches
|
|
|
21
21
|
|
|
22
22
|
from tradechart.config.logger import get_logger
|
|
23
23
|
from tradechart.config.settings import get_settings
|
|
24
|
+
from tradechart.charts.renderer import _draw_header, save_figure
|
|
24
25
|
from tradechart.charts.themes import get_theme
|
|
25
26
|
from tradechart.charts.watermark import stamp_logo
|
|
26
27
|
from tradechart.utils.exceptions import RenderError
|
|
@@ -29,7 +30,7 @@ from tradechart.utils.exceptions import RenderError
|
|
|
29
30
|
# The canvas spans [0, fig_aspect] × [0, 1], and since fig_aspect = fw/fh the
|
|
30
31
|
# x and y data units are identical in physical size (both = fh inches/unit).
|
|
31
32
|
# A single constant therefore produces visually uniform gaps on all four sides.
|
|
32
|
-
_TILE_GAP = 0.
|
|
33
|
+
_TILE_GAP = 0.008
|
|
33
34
|
|
|
34
35
|
|
|
35
36
|
# ── Colour map: deep-red → slate-neutral → deep-green ───────────────────────
|
|
@@ -37,13 +38,11 @@ _TILE_GAP = 0.006
|
|
|
37
38
|
_HEATMAP_CMAP = mcolors.LinearSegmentedColormap.from_list(
|
|
38
39
|
"tradechart_heatmap",
|
|
39
40
|
[
|
|
40
|
-
"#
|
|
41
|
-
"#
|
|
42
|
-
"#
|
|
43
|
-
"#
|
|
44
|
-
"#
|
|
45
|
-
"#00897b",
|
|
46
|
-
"#004d40", # deep green (large gain)
|
|
41
|
+
"#8f2430",
|
|
42
|
+
"#f07178",
|
|
43
|
+
"#3a4454",
|
|
44
|
+
"#3dd68c",
|
|
45
|
+
"#147a4d",
|
|
47
46
|
],
|
|
48
47
|
N=256,
|
|
49
48
|
)
|
|
@@ -238,9 +237,10 @@ class HeatmapRenderer:
|
|
|
238
237
|
log.detail("Heatmap layout: %s (%d tiles)", weight_note, len(layout))
|
|
239
238
|
|
|
240
239
|
# ── Figure ───────────────────────────────────────────────────────────
|
|
241
|
-
fig, ax = plt.subplots(figsize=(fw, fh))
|
|
240
|
+
fig, ax = plt.subplots(figsize=(fw, fh), dpi=settings.dpi)
|
|
242
241
|
fig.patch.set_facecolor(theme.bg_color)
|
|
243
242
|
ax.set_facecolor(theme.bg_color)
|
|
243
|
+
fig.subplots_adjust(left=0.055, right=0.915, top=0.80, bottom=0.14)
|
|
244
244
|
ax.set_xlim(0, fig_aspect)
|
|
245
245
|
ax.set_ylim(0, 1.0)
|
|
246
246
|
ax.set_aspect("auto")
|
|
@@ -254,13 +254,18 @@ class HeatmapRenderer:
|
|
|
254
254
|
price = prices.get(ticker)
|
|
255
255
|
color = _tile_color(pct, vrange)
|
|
256
256
|
|
|
257
|
-
|
|
257
|
+
tile_w = (tx1 - tx0) - 2 * _TILE_GAP
|
|
258
|
+
tile_h = (ty1 - ty0) - 2 * _TILE_GAP
|
|
259
|
+
radius = min(0.012, tile_w * 0.08, tile_h * 0.08)
|
|
260
|
+
rect = mpatches.FancyBboxPatch(
|
|
258
261
|
(tx0 + _TILE_GAP, ty0 + _TILE_GAP),
|
|
259
|
-
|
|
260
|
-
|
|
262
|
+
tile_w,
|
|
263
|
+
tile_h,
|
|
264
|
+
boxstyle=f"round,pad=0,rounding_size={radius:.4f}",
|
|
261
265
|
facecolor=color,
|
|
262
266
|
edgecolor="none",
|
|
263
267
|
linewidth=0,
|
|
268
|
+
mutation_aspect=1,
|
|
264
269
|
zorder=2,
|
|
265
270
|
)
|
|
266
271
|
ax.add_patch(rect)
|
|
@@ -294,17 +299,20 @@ class HeatmapRenderer:
|
|
|
294
299
|
ty_t = cy
|
|
295
300
|
ty_p = ty_pr = None
|
|
296
301
|
|
|
302
|
+
label_face, figure_face = settings.font_faces()
|
|
297
303
|
ax.text(cx, ty_t, ticker,
|
|
298
304
|
ha="center", va="center",
|
|
299
305
|
fontsize=fs_ticker, fontweight="bold",
|
|
300
|
-
color="white", zorder=3, clip_on=True
|
|
306
|
+
color="white", zorder=3, clip_on=True,
|
|
307
|
+
fontfamily=label_face)
|
|
301
308
|
|
|
302
309
|
if show_pct and ty_p is not None:
|
|
303
310
|
sign = "+" if pct >= 0 else ""
|
|
304
311
|
ax.text(cx, ty_p, f"{sign}{pct:.2f}%",
|
|
305
312
|
ha="center", va="center",
|
|
306
313
|
fontsize=fs_pct, color="white", alpha=0.92,
|
|
307
|
-
zorder=3, clip_on=True
|
|
314
|
+
zorder=3, clip_on=True,
|
|
315
|
+
fontfamily=figure_face)
|
|
308
316
|
|
|
309
317
|
if show_price and ty_pr is not None:
|
|
310
318
|
price_str = (
|
|
@@ -315,13 +323,15 @@ class HeatmapRenderer:
|
|
|
315
323
|
ax.text(cx, ty_pr, price_str,
|
|
316
324
|
ha="center", va="center",
|
|
317
325
|
fontsize=fs_price, color="white", alpha=0.72,
|
|
318
|
-
zorder=3, clip_on=True
|
|
326
|
+
zorder=3, clip_on=True,
|
|
327
|
+
fontfamily=figure_face)
|
|
319
328
|
|
|
320
329
|
# ── Title ─────────────────────────────────────────────────────────────
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
330
|
+
weight_note = "market-cap weighted" if has_caps else "equal weight"
|
|
331
|
+
_draw_header(
|
|
332
|
+
fig, theme,
|
|
333
|
+
title=label,
|
|
334
|
+
subtitle=f"{duration} · performance · {weight_note}",
|
|
325
335
|
)
|
|
326
336
|
|
|
327
337
|
# ── Colour-bar legend ──────────────────────────────────────────────────
|
|
@@ -334,26 +344,23 @@ class HeatmapRenderer:
|
|
|
334
344
|
sm, ax=ax, orientation="horizontal",
|
|
335
345
|
fraction=0.025, pad=0.03, aspect=50,
|
|
336
346
|
)
|
|
337
|
-
cbar.set_label("%
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
347
|
+
cbar.set_label("% change", color=theme.muted_color, fontsize=8)
|
|
348
|
+
_label_face, figure_face = settings.font_faces()
|
|
349
|
+
try:
|
|
350
|
+
cbar.ax.tick_params(
|
|
351
|
+
colors=theme.muted_color, labelsize=8, length=0, labelfontfamily=figure_face,
|
|
352
|
+
)
|
|
353
|
+
except TypeError:
|
|
354
|
+
cbar.ax.tick_params(colors=theme.muted_color, labelsize=8, length=0)
|
|
355
|
+
cbar.ax.xaxis.label.set_fontfamily(figure_face)
|
|
356
|
+
cbar.outline.set_visible(False)
|
|
343
357
|
|
|
344
358
|
if settings.watermark_enabled:
|
|
345
359
|
stamp_logo(fig, provider=provider)
|
|
346
360
|
|
|
347
361
|
out_file = output_path.with_suffix(f".{fmt}")
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
pil_kwargs = {"compress_level": 6, "optimize": True}
|
|
351
|
-
elif fmt in ("jpg", "jpeg", "webp"):
|
|
352
|
-
pil_kwargs = {"quality": 82, "optimize": True}
|
|
353
|
-
save_kwargs: dict = {"dpi": settings.dpi, "facecolor": fig.get_facecolor(), "bbox_inches": "tight"}
|
|
354
|
-
if pil_kwargs:
|
|
355
|
-
save_kwargs["pil_kwargs"] = pil_kwargs
|
|
356
|
-
fig.savefig(out_file, **save_kwargs)
|
|
362
|
+
with plt.rc_context({"svg.fonttype": "none", "savefig.bbox": None}):
|
|
363
|
+
save_figure(fig, out_file, fmt, settings.dpi)
|
|
357
364
|
plt.close(fig)
|
|
358
365
|
log.detail("Saved heatmap → %s", out_file)
|
|
359
366
|
return out_file
|