forexsmartbot 3.2.0__tar.gz → 3.2.2__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.
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/PKG-INFO +46 -13
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/README.md +45 -12
- forexsmartbot-3.2.2/forexsmartbot/analytics/__init__.py +43 -0
- forexsmartbot-3.2.2/forexsmartbot/analytics/live_metrics.py +161 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/analytics/portfolio_analytics.py +20 -11
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/analytics/risk_analytics.py +6 -1
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/core/strategy.py +2 -9
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/services/calculation_engine.py +15 -6
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/strategies/__init__.py +15 -2
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/strategies/multi_timeframe_strategy.py +38 -12
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/strategies/sma_crossover.py +4 -18
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/ui/analytics_dialog.py +33 -19
- forexsmartbot-3.2.2/forexsmartbot/ui/analytics_widget.py +202 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/ui/enhanced_main_window.py +7 -0
- forexsmartbot-3.2.2/forexsmartbot/utils/native_indicators.py +200 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot.egg-info/PKG-INFO +46 -13
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot.egg-info/SOURCES.txt +9 -1
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot.egg-info/requires.txt +2 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/pyproject.toml +2 -2
- forexsmartbot-3.2.2/tests/test_config.py +48 -0
- forexsmartbot-3.2.2/tests/test_live_metrics.py +70 -0
- forexsmartbot-3.2.2/tests/test_multi_timeframe_strategy.py +119 -0
- forexsmartbot-3.2.2/tests/test_native_indicators.py +109 -0
- forexsmartbot-3.2.2/tests/test_risk.py +121 -0
- forexsmartbot-3.2.2/tests/test_strategies.py +129 -0
- forexsmartbot-3.2.0/forexsmartbot/analytics/__init__.py +0 -28
- forexsmartbot-3.2.0/forexsmartbot/ui/analytics_widget.py +0 -68
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/LICENSE +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/__init__.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/adapters/__init__.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/adapters/brokers/__init__.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/adapters/brokers/ib_tws_broker.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/adapters/brokers/mt4_broker.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/adapters/brokers/paper_broker.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/adapters/brokers/rest_broker.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/adapters/data/__init__.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/adapters/data/alpha_vantage_provider.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/adapters/data/config.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/adapters/data/csv_provider.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/adapters/data/dummy_provider.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/adapters/data/mt4_provider.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/adapters/data/multi_provider.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/adapters/data/oanda_provider.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/adapters/data/stooq_provider.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/adapters/data/twelve_data_provider.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/adapters/data/yfinance_provider.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/analytics/chart_patterns.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/analytics/correlation_matrix.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/analytics/economic_calendar.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/analytics/enhanced_chart.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/analytics/market_depth.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/analytics/performance_attribution.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/analytics/strategy_comparison.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/analytics/trade_journal.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/brokers/mt4_bridge.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/builder/__init__.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/builder/code_generator.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/builder/strategy_builder.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/builder/strategy_template.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/cloud/__init__.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/cloud/api_client.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/cloud/api_server.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/cloud/cloud_sync.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/cloud/error_handler.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/cloud/mobile_api.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/cloud/remote_monitor.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/cloud/security.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/core/backtester.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/core/config.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/core/interfaces.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/core/paper_broker.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/core/portfolio.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/core/risk.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/core/risk_engine.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/core/trade_manager.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/gui/main_window.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/gui/theme.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/marketplace/__init__.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/marketplace/marketplace.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/marketplace/strategy_rating.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/monitoring/__init__.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/monitoring/health_check.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/monitoring/performance_tracker.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/monitoring/strategy_monitor.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/optimization/__init__.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/optimization/adaptive_parameters.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/optimization/genetic_optimizer.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/optimization/hyperparameter_optimizer.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/optimization/monte_carlo.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/optimization/multi_objective_optimizer.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/optimization/parameter_sensitivity.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/optimization/walk_forward.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/services/__init__.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/services/backtest.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/services/controller.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/services/data_streaming.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/services/enhanced_backtest.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/services/fast_trading_controller.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/services/gpu_backtest.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/services/language_manager.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/services/notification_service.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/services/persistence.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/services/startup_manager.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/strategies/adaptive_trend_flow.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/strategies/breakout_atr.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/strategies/ensemble_ml_strategy.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/strategies/fear_index.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/strategies/lstm_strategy.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/strategies/mean_reversion.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/strategies/ml_adaptive_supertrend.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/strategies/momentum_breakout.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/strategies/news_trading.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/strategies/rl_strategy.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/strategies/rsi_reversion.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/strategies/scalping_ma.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/strategies/svm_strategy.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/strategies/transformer_strategy.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/testing/__init__.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/testing/ci_cd_pipeline.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/testing/paper_account_tester.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/testing/strategy_sandbox.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/ui/__init__.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/ui/backtest_dialog.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/ui/charts.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/ui/cloud_dialog.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/ui/enhanced_charts.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/ui/export_dialog.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/ui/main_window.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/ui/marketplace_dialog.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/ui/monitoring_dialog.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/ui/monitoring_widget.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/ui/optimization_dialog.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/ui/settings_dialog.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/ui/simple_chart.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/ui/strategy_builder_dialog.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/ui/theme.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/ui/tradingview_chart.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/utils/__init__.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/utils/gpu_numpy.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot/utils/gpu_utils.py +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot.egg-info/dependency_links.txt +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot.egg-info/entry_points.txt +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/forexsmartbot.egg-info/top_level.txt +0 -0
- {forexsmartbot-3.2.0 → forexsmartbot-3.2.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: forexsmartbot
|
|
3
|
-
Version: 3.2.
|
|
3
|
+
Version: 3.2.2
|
|
4
4
|
Summary: Professional forex trading bot with advanced risk management and strategy plugins
|
|
5
5
|
Author-email: VoxHash <contact@voxhash.dev>
|
|
6
6
|
License: MIT
|
|
@@ -30,7 +30,7 @@ Requires-Dist: mplfinance>=0.12.10
|
|
|
30
30
|
Requires-Dist: TA-Lib>=0.6.7
|
|
31
31
|
Requires-Dist: requests>=2.31.0
|
|
32
32
|
Requires-Dist: ib-insync>=0.9.86
|
|
33
|
-
Requires-Dist: win10toast>=0.9
|
|
33
|
+
Requires-Dist: win10toast>=0.9; sys_platform == "win32"
|
|
34
34
|
Provides-Extra: dev
|
|
35
35
|
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
36
36
|
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
@@ -42,13 +42,17 @@ Dynamic: license-file
|
|
|
42
42
|
|
|
43
43
|
# ForexSmartBot
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+

|
|
46
|
+

|
|
47
|
+

|
|
48
|
+

|
|
49
|
+
|
|
50
|
+
|
|
49
51
|
|
|
50
52
|
> Professional-grade desktop application for automated forex trading with advanced risk management, multiple trading strategies, and real-time portfolio monitoring.
|
|
51
53
|
|
|
54
|
+
|
|
55
|
+
|
|
52
56
|
## ✨ Features
|
|
53
57
|
|
|
54
58
|
- **Multi-Strategy Trading**: 17+ built-in strategies including 7 ML-based approaches
|
|
@@ -60,6 +64,8 @@ Dynamic: license-file
|
|
|
60
64
|
- **Strategy Builder**: Visual strategy construction with code generation
|
|
61
65
|
- **Strategy Marketplace**: Community-driven strategy sharing platform
|
|
62
66
|
|
|
67
|
+
|
|
68
|
+
|
|
63
69
|
## 🧭 Table of Contents
|
|
64
70
|
|
|
65
71
|
- [Quick Start](#-quick-start)
|
|
@@ -70,6 +76,8 @@ Dynamic: license-file
|
|
|
70
76
|
- [Contributing](#-contributing)
|
|
71
77
|
- [License](#-license)
|
|
72
78
|
|
|
79
|
+
|
|
80
|
+
|
|
73
81
|
## 🚀 Quick Start
|
|
74
82
|
|
|
75
83
|
```bash
|
|
@@ -84,12 +92,18 @@ For detailed installation instructions, see [docs/installation.md](docs/Installa
|
|
|
84
92
|
|
|
85
93
|
## 💿 Installation
|
|
86
94
|
|
|
95
|
+
|
|
96
|
+
|
|
87
97
|
### From PyPI (Recommended)
|
|
98
|
+
|
|
88
99
|
```bash
|
|
89
100
|
pip install forexsmartbot
|
|
90
101
|
```
|
|
91
102
|
|
|
103
|
+
|
|
104
|
+
|
|
92
105
|
### From Source
|
|
106
|
+
|
|
93
107
|
```bash
|
|
94
108
|
git clone https://github.com/VoxHash/ForexSmartBot.git
|
|
95
109
|
cd ForexSmartBot
|
|
@@ -97,7 +111,10 @@ pip install -r requirements.txt
|
|
|
97
111
|
python app.py
|
|
98
112
|
```
|
|
99
113
|
|
|
114
|
+
|
|
115
|
+
|
|
100
116
|
### With GPU Acceleration (Optional)
|
|
117
|
+
|
|
101
118
|
```bash
|
|
102
119
|
# For CUDA 12.x
|
|
103
120
|
pip install cupy-cuda12x
|
|
@@ -108,8 +125,22 @@ pip install cupy-cuda11x
|
|
|
108
125
|
|
|
109
126
|
See [docs/GPU_ACCELERATION.md](docs/GPU_ACCELERATION.md) for detailed setup instructions.
|
|
110
127
|
|
|
128
|
+
### With Native Rust Indicators (Optional)
|
|
129
|
+
|
|
130
|
+
Lower-memory SMA/ATR/RSI and parallel batch SMA via PyO3 (`native/fsb_core`). Requires [Rust](https://rustup.rs/) and [maturin](https://www.maturin.rs/).
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
# once: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
|
134
|
+
pip install maturin
|
|
135
|
+
cd native/fsb_core && maturin develop --release
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Without the extension, the same Python APIs use a NumPy fallback automatically. See [docs/PERFORMANCE_TUNING.md](docs/PERFORMANCE_TUNING.md).
|
|
139
|
+
|
|
111
140
|
## 🛠 Usage
|
|
112
141
|
|
|
142
|
+
|
|
143
|
+
|
|
113
144
|
### Basic Workflow
|
|
114
145
|
|
|
115
146
|
1. Launch the application: `python app.py`
|
|
@@ -122,12 +153,14 @@ For advanced usage, see [docs/usage.md](docs/QUICK_START_V3.1.0.md) and [docs/cl
|
|
|
122
153
|
|
|
123
154
|
## ⚙️ Configuration
|
|
124
155
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
|
128
|
-
| `
|
|
129
|
-
| `
|
|
130
|
-
| `
|
|
156
|
+
|
|
157
|
+
| Variable | Description | Default |
|
|
158
|
+
| ----------------- | ------------------------- | ------- |
|
|
159
|
+
| `INITIAL_BALANCE` | Starting account balance | 10000.0 |
|
|
160
|
+
| `RISK_PER_TRADE` | Risk percentage per trade | 0.02 |
|
|
161
|
+
| `MAX_LEVERAGE` | Maximum leverage | 1:100 |
|
|
162
|
+
| `DATA_INTERVAL` | Data update interval | 1h |
|
|
163
|
+
|
|
131
164
|
|
|
132
165
|
Full configuration reference: [docs/Configuration-Guide.md](docs/Configuration-Guide.md)
|
|
133
166
|
|
|
@@ -164,7 +197,7 @@ This project is licensed under the terms in [LICENSE](LICENSE).
|
|
|
164
197
|
- **Documentation**: [docs/](docs/)
|
|
165
198
|
- **FAQ**: [docs/FAQ.md](docs/FAQ.md)
|
|
166
199
|
- **Issues**: [GitHub Issues](https://github.com/VoxHash/ForexSmartBot/issues)
|
|
167
|
-
- **Email**: contact@voxhash.dev
|
|
200
|
+
- **Email**: [contact@voxhash.dev](mailto:contact@voxhash.dev)
|
|
168
201
|
|
|
169
202
|
See [SUPPORT.md](SUPPORT.md) for more support options.
|
|
170
203
|
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
# ForexSmartBot
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+

|
|
4
|
+

|
|
5
|
+

|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
|
|
7
9
|
|
|
8
10
|
> Professional-grade desktop application for automated forex trading with advanced risk management, multiple trading strategies, and real-time portfolio monitoring.
|
|
9
11
|
|
|
12
|
+
|
|
13
|
+
|
|
10
14
|
## ✨ Features
|
|
11
15
|
|
|
12
16
|
- **Multi-Strategy Trading**: 17+ built-in strategies including 7 ML-based approaches
|
|
@@ -18,6 +22,8 @@
|
|
|
18
22
|
- **Strategy Builder**: Visual strategy construction with code generation
|
|
19
23
|
- **Strategy Marketplace**: Community-driven strategy sharing platform
|
|
20
24
|
|
|
25
|
+
|
|
26
|
+
|
|
21
27
|
## 🧭 Table of Contents
|
|
22
28
|
|
|
23
29
|
- [Quick Start](#-quick-start)
|
|
@@ -28,6 +34,8 @@
|
|
|
28
34
|
- [Contributing](#-contributing)
|
|
29
35
|
- [License](#-license)
|
|
30
36
|
|
|
37
|
+
|
|
38
|
+
|
|
31
39
|
## 🚀 Quick Start
|
|
32
40
|
|
|
33
41
|
```bash
|
|
@@ -42,12 +50,18 @@ For detailed installation instructions, see [docs/installation.md](docs/Installa
|
|
|
42
50
|
|
|
43
51
|
## 💿 Installation
|
|
44
52
|
|
|
53
|
+
|
|
54
|
+
|
|
45
55
|
### From PyPI (Recommended)
|
|
56
|
+
|
|
46
57
|
```bash
|
|
47
58
|
pip install forexsmartbot
|
|
48
59
|
```
|
|
49
60
|
|
|
61
|
+
|
|
62
|
+
|
|
50
63
|
### From Source
|
|
64
|
+
|
|
51
65
|
```bash
|
|
52
66
|
git clone https://github.com/VoxHash/ForexSmartBot.git
|
|
53
67
|
cd ForexSmartBot
|
|
@@ -55,7 +69,10 @@ pip install -r requirements.txt
|
|
|
55
69
|
python app.py
|
|
56
70
|
```
|
|
57
71
|
|
|
72
|
+
|
|
73
|
+
|
|
58
74
|
### With GPU Acceleration (Optional)
|
|
75
|
+
|
|
59
76
|
```bash
|
|
60
77
|
# For CUDA 12.x
|
|
61
78
|
pip install cupy-cuda12x
|
|
@@ -66,8 +83,22 @@ pip install cupy-cuda11x
|
|
|
66
83
|
|
|
67
84
|
See [docs/GPU_ACCELERATION.md](docs/GPU_ACCELERATION.md) for detailed setup instructions.
|
|
68
85
|
|
|
86
|
+
### With Native Rust Indicators (Optional)
|
|
87
|
+
|
|
88
|
+
Lower-memory SMA/ATR/RSI and parallel batch SMA via PyO3 (`native/fsb_core`). Requires [Rust](https://rustup.rs/) and [maturin](https://www.maturin.rs/).
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
# once: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
|
92
|
+
pip install maturin
|
|
93
|
+
cd native/fsb_core && maturin develop --release
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Without the extension, the same Python APIs use a NumPy fallback automatically. See [docs/PERFORMANCE_TUNING.md](docs/PERFORMANCE_TUNING.md).
|
|
97
|
+
|
|
69
98
|
## 🛠 Usage
|
|
70
99
|
|
|
100
|
+
|
|
101
|
+
|
|
71
102
|
### Basic Workflow
|
|
72
103
|
|
|
73
104
|
1. Launch the application: `python app.py`
|
|
@@ -80,12 +111,14 @@ For advanced usage, see [docs/usage.md](docs/QUICK_START_V3.1.0.md) and [docs/cl
|
|
|
80
111
|
|
|
81
112
|
## ⚙️ Configuration
|
|
82
113
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
|
86
|
-
| `
|
|
87
|
-
| `
|
|
88
|
-
| `
|
|
114
|
+
|
|
115
|
+
| Variable | Description | Default |
|
|
116
|
+
| ----------------- | ------------------------- | ------- |
|
|
117
|
+
| `INITIAL_BALANCE` | Starting account balance | 10000.0 |
|
|
118
|
+
| `RISK_PER_TRADE` | Risk percentage per trade | 0.02 |
|
|
119
|
+
| `MAX_LEVERAGE` | Maximum leverage | 1:100 |
|
|
120
|
+
| `DATA_INTERVAL` | Data update interval | 1h |
|
|
121
|
+
|
|
89
122
|
|
|
90
123
|
Full configuration reference: [docs/Configuration-Guide.md](docs/Configuration-Guide.md)
|
|
91
124
|
|
|
@@ -122,7 +155,7 @@ This project is licensed under the terms in [LICENSE](LICENSE).
|
|
|
122
155
|
- **Documentation**: [docs/](docs/)
|
|
123
156
|
- **FAQ**: [docs/FAQ.md](docs/FAQ.md)
|
|
124
157
|
- **Issues**: [GitHub Issues](https://github.com/VoxHash/ForexSmartBot/issues)
|
|
125
|
-
- **Email**: contact@voxhash.dev
|
|
158
|
+
- **Email**: [contact@voxhash.dev](mailto:contact@voxhash.dev)
|
|
126
159
|
|
|
127
160
|
See [SUPPORT.md](SUPPORT.md) for more support options.
|
|
128
161
|
|
|
@@ -132,4 +165,4 @@ This application is for educational and legitimate business purposes only. Users
|
|
|
132
165
|
|
|
133
166
|
---
|
|
134
167
|
|
|
135
|
-
Made with ❤️ by [VoxHash Technologies](https://voxhash.dev)
|
|
168
|
+
Made with ❤️ by [VoxHash Technologies](https://voxhash.dev)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Analytics module for ForexSmartBot v3.2.0
|
|
3
|
+
Provides portfolio analytics, risk analytics, and advanced charting features.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from .portfolio_analytics import PortfolioAnalytics
|
|
7
|
+
from .risk_analytics import RiskAnalytics
|
|
8
|
+
from .chart_patterns import ChartPatternRecognizer
|
|
9
|
+
from .performance_attribution import PerformanceAttribution
|
|
10
|
+
from .live_metrics import LiveMetricsSnapshot, build_live_metrics
|
|
11
|
+
|
|
12
|
+
# Qt-backed widgets are optional (headless / test environments may lack PyQt6)
|
|
13
|
+
try:
|
|
14
|
+
from .market_depth import MarketDepthWidget, MarketDepthProvider
|
|
15
|
+
from .correlation_matrix import CorrelationMatrixWidget, CorrelationAnalyzer
|
|
16
|
+
from .economic_calendar import EconomicCalendarWidget, EconomicCalendarProvider
|
|
17
|
+
from .trade_journal import TradeJournalWidget, TradeJournalManager
|
|
18
|
+
except ImportError: # pragma: no cover - UI optional
|
|
19
|
+
MarketDepthWidget = None # type: ignore[misc, assignment]
|
|
20
|
+
MarketDepthProvider = None # type: ignore[misc, assignment]
|
|
21
|
+
CorrelationMatrixWidget = None # type: ignore[misc, assignment]
|
|
22
|
+
CorrelationAnalyzer = None # type: ignore[misc, assignment]
|
|
23
|
+
EconomicCalendarWidget = None # type: ignore[misc, assignment]
|
|
24
|
+
EconomicCalendarProvider = None # type: ignore[misc, assignment]
|
|
25
|
+
TradeJournalWidget = None # type: ignore[misc, assignment]
|
|
26
|
+
TradeJournalManager = None # type: ignore[misc, assignment]
|
|
27
|
+
|
|
28
|
+
__all__ = [
|
|
29
|
+
'PortfolioAnalytics',
|
|
30
|
+
'RiskAnalytics',
|
|
31
|
+
'ChartPatternRecognizer',
|
|
32
|
+
'PerformanceAttribution',
|
|
33
|
+
'MarketDepthWidget',
|
|
34
|
+
'MarketDepthProvider',
|
|
35
|
+
'CorrelationMatrixWidget',
|
|
36
|
+
'CorrelationAnalyzer',
|
|
37
|
+
'EconomicCalendarWidget',
|
|
38
|
+
'EconomicCalendarProvider',
|
|
39
|
+
'TradeJournalWidget',
|
|
40
|
+
'TradeJournalManager',
|
|
41
|
+
'LiveMetricsSnapshot',
|
|
42
|
+
'build_live_metrics',
|
|
43
|
+
]
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Live portfolio and risk metrics for the analytics dashboard.
|
|
3
|
+
|
|
4
|
+
Pure computation (no Qt) so the snapshot can be unit-tested and reused by
|
|
5
|
+
dialogs, widgets, and remote monitors.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from dataclasses import asdict, dataclass
|
|
11
|
+
from datetime import datetime
|
|
12
|
+
from typing import Any, Dict, List, Optional, Sequence
|
|
13
|
+
|
|
14
|
+
from ..core.interfaces import Trade
|
|
15
|
+
from .portfolio_analytics import PortfolioAnalytics
|
|
16
|
+
from .risk_analytics import RiskAnalytics
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass
|
|
20
|
+
class LiveMetricsSnapshot:
|
|
21
|
+
"""Point-in-time analytics snapshot for UI and monitoring."""
|
|
22
|
+
|
|
23
|
+
timestamp: datetime
|
|
24
|
+
equity: float
|
|
25
|
+
balance: float
|
|
26
|
+
realized_pnl: float
|
|
27
|
+
unrealized_pnl: float
|
|
28
|
+
daily_pnl: float
|
|
29
|
+
open_positions: int
|
|
30
|
+
total_trades: int
|
|
31
|
+
win_rate: float
|
|
32
|
+
profit_factor: float
|
|
33
|
+
sharpe_ratio: float
|
|
34
|
+
sortino_ratio: float
|
|
35
|
+
max_drawdown: float
|
|
36
|
+
max_drawdown_pct: float
|
|
37
|
+
current_drawdown: float
|
|
38
|
+
var_95: float
|
|
39
|
+
cvar_95: float
|
|
40
|
+
volatility: float
|
|
41
|
+
average_win: float
|
|
42
|
+
average_loss: float
|
|
43
|
+
|
|
44
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
45
|
+
"""Serialize for tables / JSON."""
|
|
46
|
+
data = asdict(self)
|
|
47
|
+
data["timestamp"] = self.timestamp.isoformat()
|
|
48
|
+
return data
|
|
49
|
+
|
|
50
|
+
def card_metrics(self) -> List[tuple]:
|
|
51
|
+
"""Primary KPI cards: (label, formatted value, tone)."""
|
|
52
|
+
tone_pnl = "positive" if self.daily_pnl >= 0 else "negative"
|
|
53
|
+
tone_eq = "positive" if self.unrealized_pnl + self.realized_pnl >= 0 else "negative"
|
|
54
|
+
return [
|
|
55
|
+
("Equity", f"${self.equity:,.2f}", tone_eq),
|
|
56
|
+
("Daily P&L", f"${self.daily_pnl:,.2f}", tone_pnl),
|
|
57
|
+
("Win Rate", f"{self.win_rate:.1f}%", "neutral"),
|
|
58
|
+
("Sharpe", f"{self.sharpe_ratio:.3f}", "neutral"),
|
|
59
|
+
("Max DD", f"{self.max_drawdown_pct:.2f}%", "negative" if self.max_drawdown_pct else "neutral"),
|
|
60
|
+
("VaR 95%", f"{self.var_95:.4f}", "neutral"),
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _portfolio_trades(portfolio) -> List[Trade]:
|
|
65
|
+
"""Extract Trade list from Portfolio or trade sequence."""
|
|
66
|
+
if portfolio is None:
|
|
67
|
+
return []
|
|
68
|
+
if hasattr(portfolio, "trades"):
|
|
69
|
+
return list(portfolio.trades)
|
|
70
|
+
if isinstance(portfolio, Sequence):
|
|
71
|
+
return list(portfolio)
|
|
72
|
+
return []
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _sync_portfolio_analytics(analytics: PortfolioAnalytics, portfolio) -> None:
|
|
76
|
+
"""Load trades and equity curve from a live Portfolio."""
|
|
77
|
+
analytics.trades = _portfolio_trades(portfolio)
|
|
78
|
+
analytics.equity_curve = []
|
|
79
|
+
if portfolio is None:
|
|
80
|
+
return
|
|
81
|
+
timestamps = getattr(portfolio, "timestamps", None)
|
|
82
|
+
equity_history = getattr(portfolio, "equity_history", None)
|
|
83
|
+
if timestamps is not None and equity_history is not None:
|
|
84
|
+
ts = list(timestamps)
|
|
85
|
+
eq = list(equity_history)
|
|
86
|
+
n = min(len(ts), len(eq))
|
|
87
|
+
analytics.equity_curve = list(zip(ts[:n], eq[:n]))
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def _sync_risk_analytics(risk: RiskAnalytics, portfolio) -> None:
|
|
91
|
+
"""Load trades into RiskAnalytics from a live Portfolio."""
|
|
92
|
+
risk.trades = _portfolio_trades(portfolio)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def build_live_metrics(portfolio, *, now: Optional[datetime] = None) -> LiveMetricsSnapshot:
|
|
96
|
+
"""
|
|
97
|
+
Build a live metrics snapshot from a Portfolio (or trade container).
|
|
98
|
+
|
|
99
|
+
Uses Portfolio balance/equity when available; otherwise derives from trades.
|
|
100
|
+
"""
|
|
101
|
+
now = now or datetime.now()
|
|
102
|
+
portfolio_analytics = PortfolioAnalytics()
|
|
103
|
+
risk_analytics = RiskAnalytics()
|
|
104
|
+
_sync_portfolio_analytics(portfolio_analytics, portfolio)
|
|
105
|
+
_sync_risk_analytics(risk_analytics, portfolio)
|
|
106
|
+
|
|
107
|
+
summary = portfolio_analytics.get_performance_summary()
|
|
108
|
+
max_dd = portfolio_analytics.calculate_max_drawdown()
|
|
109
|
+
var_result = risk_analytics.calculate_var(confidence_level=0.95)
|
|
110
|
+
cvar_result = risk_analytics.calculate_cvar(confidence_level=0.95)
|
|
111
|
+
|
|
112
|
+
returns = risk_analytics._get_returns()
|
|
113
|
+
volatility = float(returns.std()) if len(returns) >= 2 else 0.0
|
|
114
|
+
|
|
115
|
+
if portfolio is not None and hasattr(portfolio, "get_total_equity"):
|
|
116
|
+
equity = float(portfolio.get_total_equity())
|
|
117
|
+
balance = float(portfolio.get_total_balance())
|
|
118
|
+
realized = float(portfolio.get_realized_pnl())
|
|
119
|
+
unrealized = float(portfolio.get_unrealized_pnl())
|
|
120
|
+
daily = float(portfolio.get_daily_pnl())
|
|
121
|
+
open_positions = len(getattr(portfolio, "positions", {}) or {})
|
|
122
|
+
current_dd = float(portfolio.get_current_drawdown()) * 100.0
|
|
123
|
+
else:
|
|
124
|
+
equity = 10000.0 + float(summary.get("total_pnl", 0.0))
|
|
125
|
+
balance = equity
|
|
126
|
+
realized = float(summary.get("total_pnl", 0.0))
|
|
127
|
+
unrealized = 0.0
|
|
128
|
+
daily = realized
|
|
129
|
+
open_positions = 0
|
|
130
|
+
current_dd = float(max_dd.get("max_drawdown_pct", 0.0))
|
|
131
|
+
|
|
132
|
+
profit_factor = summary.get("profit_factor", 0.0)
|
|
133
|
+
if profit_factor == float("inf"):
|
|
134
|
+
profit_factor = 0.0
|
|
135
|
+
|
|
136
|
+
sortino = summary.get("sortino_ratio", 0.0)
|
|
137
|
+
if sortino == float("inf"):
|
|
138
|
+
sortino = 0.0
|
|
139
|
+
|
|
140
|
+
return LiveMetricsSnapshot(
|
|
141
|
+
timestamp=now,
|
|
142
|
+
equity=equity,
|
|
143
|
+
balance=balance,
|
|
144
|
+
realized_pnl=realized,
|
|
145
|
+
unrealized_pnl=unrealized,
|
|
146
|
+
daily_pnl=daily,
|
|
147
|
+
open_positions=open_positions,
|
|
148
|
+
total_trades=int(summary.get("total_trades", 0)),
|
|
149
|
+
win_rate=float(summary.get("win_rate", 0.0)),
|
|
150
|
+
profit_factor=float(profit_factor),
|
|
151
|
+
sharpe_ratio=float(summary.get("sharpe_ratio", 0.0)),
|
|
152
|
+
sortino_ratio=float(sortino),
|
|
153
|
+
max_drawdown=float(max_dd.get("max_drawdown", 0.0)),
|
|
154
|
+
max_drawdown_pct=float(max_dd.get("max_drawdown_pct", 0.0)),
|
|
155
|
+
current_drawdown=current_dd,
|
|
156
|
+
var_95=float(var_result.get("var", 0.0)),
|
|
157
|
+
cvar_95=float(cvar_result.get("cvar", 0.0)),
|
|
158
|
+
volatility=volatility,
|
|
159
|
+
average_win=float(summary.get("average_win", 0.0)),
|
|
160
|
+
average_loss=float(summary.get("average_loss", 0.0)),
|
|
161
|
+
)
|
|
@@ -284,20 +284,29 @@ class PortfolioAnalytics:
|
|
|
284
284
|
Calculate portfolio metrics (alias for get_performance_summary for compatibility).
|
|
285
285
|
|
|
286
286
|
Args:
|
|
287
|
-
portfolio: Optional portfolio object
|
|
287
|
+
portfolio: Optional portfolio object; when provided, trades and equity
|
|
288
|
+
history are loaded for the calculation.
|
|
288
289
|
|
|
289
290
|
Returns:
|
|
290
291
|
Dictionary of performance metrics
|
|
291
292
|
"""
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
293
|
+
if portfolio is None:
|
|
294
|
+
return self.get_performance_summary()
|
|
295
|
+
|
|
296
|
+
original_trades = self.trades
|
|
297
|
+
original_equity = self.equity_curve
|
|
298
|
+
try:
|
|
299
|
+
if hasattr(portfolio, "trades"):
|
|
300
|
+
self.trades = list(portfolio.trades)
|
|
301
|
+
timestamps = getattr(portfolio, "timestamps", None)
|
|
302
|
+
equity_history = getattr(portfolio, "equity_history", None)
|
|
303
|
+
if timestamps is not None and equity_history is not None:
|
|
304
|
+
ts = list(timestamps)
|
|
305
|
+
eq = list(equity_history)
|
|
306
|
+
n = min(len(ts), len(eq))
|
|
307
|
+
self.equity_curve = list(zip(ts[:n], eq[:n]))
|
|
308
|
+
return self.get_performance_summary()
|
|
309
|
+
finally:
|
|
298
310
|
self.trades = original_trades
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
# Otherwise use internal trades
|
|
302
|
-
return self.get_performance_summary()
|
|
311
|
+
self.equity_curve = original_equity
|
|
303
312
|
|
|
@@ -7,7 +7,6 @@ import numpy as np
|
|
|
7
7
|
import pandas as pd
|
|
8
8
|
from typing import Dict, List, Optional, Tuple
|
|
9
9
|
from datetime import datetime, timedelta
|
|
10
|
-
from scipy import stats
|
|
11
10
|
from ..core.interfaces import Trade, Position
|
|
12
11
|
|
|
13
12
|
|
|
@@ -245,6 +244,12 @@ class RiskAnalytics:
|
|
|
245
244
|
def _calculate_parametric_var(self, returns: np.ndarray,
|
|
246
245
|
confidence_level: float) -> float:
|
|
247
246
|
"""Calculate VaR using parametric (variance-covariance) method."""
|
|
247
|
+
try:
|
|
248
|
+
from scipy import stats
|
|
249
|
+
except ImportError as exc:
|
|
250
|
+
raise ImportError(
|
|
251
|
+
"scipy is required for parametric VaR; use method='historical'"
|
|
252
|
+
) from exc
|
|
248
253
|
mean_return = np.mean(returns)
|
|
249
254
|
std_return = np.std(returns)
|
|
250
255
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import pandas as pd
|
|
2
|
-
import numpy as np
|
|
3
2
|
|
|
4
3
|
class Strategy:
|
|
5
4
|
"""Simple trend/volatility aware strategy:
|
|
@@ -13,14 +12,8 @@ class Strategy:
|
|
|
13
12
|
self.atr_window = atr_window
|
|
14
13
|
|
|
15
14
|
def indicators(self, df: pd.DataFrame) -> pd.DataFrame:
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
out['SMA_slow'] = out['Close'].rolling(self.slow).mean()
|
|
19
|
-
tr = np.maximum(out['High']-out['Low'],
|
|
20
|
-
np.maximum(abs(out['High']-out['Close'].shift(1)),
|
|
21
|
-
abs(out['Low']-out['Close'].shift(1))))
|
|
22
|
-
out['ATR'] = tr.rolling(self.atr_window).mean()
|
|
23
|
-
return out
|
|
15
|
+
from ..utils.native_indicators import apply_sma_atr_indicators
|
|
16
|
+
return apply_sma_atr_indicators(df, self.fast, self.slow, self.atr_window)
|
|
24
17
|
|
|
25
18
|
def signal(self, df: pd.DataFrame) -> int:
|
|
26
19
|
if len(df) < max(self.fast, self.slow) + 2:
|
|
@@ -68,27 +68,36 @@ class CalculationEngine:
|
|
|
68
68
|
columns=returns_df.columns)
|
|
69
69
|
|
|
70
70
|
@staticmethod
|
|
71
|
-
@jit(nopython=True)
|
|
72
71
|
def fast_rolling_mean(values: np.ndarray, window: int) -> np.ndarray:
|
|
72
|
+
"""Fast rolling mean: prefer Rust ``fsb_core``, else Numba, else NumPy."""
|
|
73
|
+
from ..utils.native_indicators import native_available, sma
|
|
74
|
+
|
|
75
|
+
if native_available():
|
|
76
|
+
return sma(values, window)
|
|
77
|
+
return CalculationEngine._numba_rolling_mean(np.asarray(values, dtype=np.float64), window)
|
|
78
|
+
|
|
79
|
+
@staticmethod
|
|
80
|
+
@jit(nopython=True)
|
|
81
|
+
def _numba_rolling_mean(values: np.ndarray, window: int) -> np.ndarray:
|
|
73
82
|
"""Fast rolling mean calculation using numba."""
|
|
74
83
|
n = len(values)
|
|
75
84
|
result = np.full(n, np.nan)
|
|
76
|
-
|
|
85
|
+
|
|
77
86
|
for i in range(window - 1, n):
|
|
78
87
|
result[i] = np.mean(values[i - window + 1:i + 1])
|
|
79
|
-
|
|
88
|
+
|
|
80
89
|
return result
|
|
81
|
-
|
|
90
|
+
|
|
82
91
|
@staticmethod
|
|
83
92
|
@jit(nopython=True)
|
|
84
93
|
def fast_rolling_std(values: np.ndarray, window: int) -> np.ndarray:
|
|
85
94
|
"""Fast rolling standard deviation calculation."""
|
|
86
95
|
n = len(values)
|
|
87
96
|
result = np.full(n, np.nan)
|
|
88
|
-
|
|
97
|
+
|
|
89
98
|
for i in range(window - 1, n):
|
|
90
99
|
result[i] = np.std(values[i - window + 1:i + 1])
|
|
91
|
-
|
|
100
|
+
|
|
92
101
|
return result
|
|
93
102
|
|
|
94
103
|
@lru_cache(maxsize=128)
|
|
@@ -110,10 +110,23 @@ RISK_LEVELS = {
|
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
def get_strategy(name: str, **params):
|
|
113
|
-
"""Get strategy instance by name.
|
|
113
|
+
"""Get strategy instance by name.
|
|
114
|
+
|
|
115
|
+
``Multi_Timeframe`` accepts an optional ``base_strategy`` (instance or registry
|
|
116
|
+
name). When omitted, it defaults to ``SMA_Crossover`` so UI / backtest call
|
|
117
|
+
sites can use ``get_strategy('Multi_Timeframe')`` with no extra kwargs.
|
|
118
|
+
"""
|
|
114
119
|
if name not in STRATEGIES:
|
|
115
120
|
raise ValueError(f"Unknown strategy: {name}")
|
|
116
|
-
|
|
121
|
+
cls = STRATEGIES[name]
|
|
122
|
+
if name == 'Multi_Timeframe':
|
|
123
|
+
base = params.pop('base_strategy', None)
|
|
124
|
+
if isinstance(base, str):
|
|
125
|
+
if base == 'Multi_Timeframe':
|
|
126
|
+
raise ValueError("Multi_Timeframe cannot wrap itself as base_strategy")
|
|
127
|
+
base = get_strategy(base)
|
|
128
|
+
return cls(base_strategy=base, **params)
|
|
129
|
+
return cls(**params)
|
|
117
130
|
|
|
118
131
|
def list_strategies():
|
|
119
132
|
"""List available strategies."""
|