investing-algorithm-framework 1.5__py3-none-any.whl → 7.25.6__py3-none-any.whl

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.
Files changed (276) hide show
  1. investing_algorithm_framework/__init__.py +192 -16
  2. investing_algorithm_framework/analysis/__init__.py +16 -0
  3. investing_algorithm_framework/analysis/backtest_data_ranges.py +202 -0
  4. investing_algorithm_framework/analysis/data.py +170 -0
  5. investing_algorithm_framework/analysis/markdown.py +91 -0
  6. investing_algorithm_framework/analysis/ranking.py +298 -0
  7. investing_algorithm_framework/app/__init__.py +29 -4
  8. investing_algorithm_framework/app/algorithm/__init__.py +7 -0
  9. investing_algorithm_framework/app/algorithm/algorithm.py +193 -0
  10. investing_algorithm_framework/app/algorithm/algorithm_factory.py +118 -0
  11. investing_algorithm_framework/app/app.py +2220 -379
  12. investing_algorithm_framework/app/app_hook.py +28 -0
  13. investing_algorithm_framework/app/context.py +1724 -0
  14. investing_algorithm_framework/app/eventloop.py +620 -0
  15. investing_algorithm_framework/app/reporting/__init__.py +27 -0
  16. investing_algorithm_framework/app/reporting/ascii.py +921 -0
  17. investing_algorithm_framework/app/reporting/backtest_report.py +349 -0
  18. investing_algorithm_framework/app/reporting/charts/__init__.py +19 -0
  19. investing_algorithm_framework/app/reporting/charts/entry_exist_signals.py +66 -0
  20. investing_algorithm_framework/app/reporting/charts/equity_curve.py +37 -0
  21. investing_algorithm_framework/app/reporting/charts/equity_curve_drawdown.py +74 -0
  22. investing_algorithm_framework/app/reporting/charts/line_chart.py +11 -0
  23. investing_algorithm_framework/app/reporting/charts/monthly_returns_heatmap.py +70 -0
  24. investing_algorithm_framework/app/reporting/charts/ohlcv_data_completeness.py +51 -0
  25. investing_algorithm_framework/app/reporting/charts/rolling_sharp_ratio.py +79 -0
  26. investing_algorithm_framework/app/reporting/charts/yearly_returns_barchart.py +55 -0
  27. investing_algorithm_framework/app/reporting/generate.py +185 -0
  28. investing_algorithm_framework/app/reporting/tables/__init__.py +11 -0
  29. investing_algorithm_framework/app/reporting/tables/key_metrics_table.py +217 -0
  30. investing_algorithm_framework/app/reporting/tables/time_metrics_table.py +80 -0
  31. investing_algorithm_framework/app/reporting/tables/trade_metrics_table.py +147 -0
  32. investing_algorithm_framework/app/reporting/tables/trades_table.py +75 -0
  33. investing_algorithm_framework/app/reporting/tables/utils.py +29 -0
  34. investing_algorithm_framework/app/reporting/templates/report_template.html.j2 +154 -0
  35. investing_algorithm_framework/app/stateless/action_handlers/__init__.py +6 -3
  36. investing_algorithm_framework/app/stateless/action_handlers/action_handler_strategy.py +1 -1
  37. investing_algorithm_framework/app/stateless/action_handlers/check_online_handler.py +2 -1
  38. investing_algorithm_framework/app/stateless/action_handlers/run_strategy_handler.py +14 -7
  39. investing_algorithm_framework/app/strategy.py +867 -60
  40. investing_algorithm_framework/app/task.py +5 -3
  41. investing_algorithm_framework/app/web/__init__.py +2 -1
  42. investing_algorithm_framework/app/web/controllers/__init__.py +2 -2
  43. investing_algorithm_framework/app/web/controllers/orders.py +3 -2
  44. investing_algorithm_framework/app/web/controllers/positions.py +2 -2
  45. investing_algorithm_framework/app/web/create_app.py +4 -2
  46. investing_algorithm_framework/app/web/schemas/position.py +1 -0
  47. investing_algorithm_framework/cli/__init__.py +0 -0
  48. investing_algorithm_framework/cli/cli.py +231 -0
  49. investing_algorithm_framework/cli/deploy_to_aws_lambda.py +501 -0
  50. investing_algorithm_framework/cli/deploy_to_azure_function.py +718 -0
  51. investing_algorithm_framework/cli/initialize_app.py +603 -0
  52. investing_algorithm_framework/cli/templates/.gitignore.template +178 -0
  53. investing_algorithm_framework/cli/templates/app.py.template +18 -0
  54. investing_algorithm_framework/cli/templates/app_aws_lambda_function.py.template +48 -0
  55. investing_algorithm_framework/cli/templates/app_azure_function.py.template +14 -0
  56. investing_algorithm_framework/cli/templates/app_web.py.template +18 -0
  57. investing_algorithm_framework/cli/templates/aws_lambda_dockerfile.template +22 -0
  58. investing_algorithm_framework/cli/templates/aws_lambda_dockerignore.template +92 -0
  59. investing_algorithm_framework/cli/templates/aws_lambda_readme.md.template +110 -0
  60. investing_algorithm_framework/cli/templates/aws_lambda_requirements.txt.template +2 -0
  61. investing_algorithm_framework/cli/templates/azure_function_function_app.py.template +65 -0
  62. investing_algorithm_framework/cli/templates/azure_function_host.json.template +15 -0
  63. investing_algorithm_framework/cli/templates/azure_function_local.settings.json.template +8 -0
  64. investing_algorithm_framework/cli/templates/azure_function_requirements.txt.template +3 -0
  65. investing_algorithm_framework/cli/templates/data_providers.py.template +17 -0
  66. investing_algorithm_framework/cli/templates/env.example.template +2 -0
  67. investing_algorithm_framework/cli/templates/env_azure_function.example.template +4 -0
  68. investing_algorithm_framework/cli/templates/market_data_providers.py.template +9 -0
  69. investing_algorithm_framework/cli/templates/readme.md.template +135 -0
  70. investing_algorithm_framework/cli/templates/requirements.txt.template +2 -0
  71. investing_algorithm_framework/cli/templates/run_backtest.py.template +20 -0
  72. investing_algorithm_framework/cli/templates/strategy.py.template +124 -0
  73. investing_algorithm_framework/cli/validate_backtest_checkpoints.py +197 -0
  74. investing_algorithm_framework/create_app.py +40 -7
  75. investing_algorithm_framework/dependency_container.py +100 -47
  76. investing_algorithm_framework/domain/__init__.py +97 -30
  77. investing_algorithm_framework/domain/algorithm_id.py +69 -0
  78. investing_algorithm_framework/domain/backtesting/__init__.py +25 -0
  79. investing_algorithm_framework/domain/backtesting/backtest.py +548 -0
  80. investing_algorithm_framework/domain/backtesting/backtest_date_range.py +113 -0
  81. investing_algorithm_framework/domain/backtesting/backtest_evaluation_focuss.py +241 -0
  82. investing_algorithm_framework/domain/backtesting/backtest_metrics.py +470 -0
  83. investing_algorithm_framework/domain/backtesting/backtest_permutation_test.py +275 -0
  84. investing_algorithm_framework/domain/backtesting/backtest_run.py +663 -0
  85. investing_algorithm_framework/domain/backtesting/backtest_summary_metrics.py +162 -0
  86. investing_algorithm_framework/domain/backtesting/backtest_utils.py +198 -0
  87. investing_algorithm_framework/domain/backtesting/combine_backtests.py +392 -0
  88. investing_algorithm_framework/domain/config.py +59 -136
  89. investing_algorithm_framework/domain/constants.py +18 -37
  90. investing_algorithm_framework/domain/data_provider.py +334 -0
  91. investing_algorithm_framework/domain/data_structures.py +42 -0
  92. investing_algorithm_framework/domain/exceptions.py +51 -1
  93. investing_algorithm_framework/domain/models/__init__.py +26 -19
  94. investing_algorithm_framework/domain/models/app_mode.py +34 -0
  95. investing_algorithm_framework/domain/models/data/__init__.py +7 -0
  96. investing_algorithm_framework/domain/models/data/data_source.py +222 -0
  97. investing_algorithm_framework/domain/models/data/data_type.py +46 -0
  98. investing_algorithm_framework/domain/models/event.py +35 -0
  99. investing_algorithm_framework/domain/models/market/__init__.py +5 -0
  100. investing_algorithm_framework/domain/models/market/market_credential.py +88 -0
  101. investing_algorithm_framework/domain/models/order/__init__.py +3 -4
  102. investing_algorithm_framework/domain/models/order/order.py +198 -65
  103. investing_algorithm_framework/domain/models/order/order_status.py +2 -2
  104. investing_algorithm_framework/domain/models/order/order_type.py +1 -3
  105. investing_algorithm_framework/domain/models/portfolio/__init__.py +6 -2
  106. investing_algorithm_framework/domain/models/portfolio/portfolio.py +98 -3
  107. investing_algorithm_framework/domain/models/portfolio/portfolio_configuration.py +37 -43
  108. investing_algorithm_framework/domain/models/portfolio/portfolio_snapshot.py +108 -11
  109. investing_algorithm_framework/domain/models/position/__init__.py +2 -1
  110. investing_algorithm_framework/domain/models/position/position.py +20 -0
  111. investing_algorithm_framework/domain/models/position/position_size.py +41 -0
  112. investing_algorithm_framework/domain/models/position/position_snapshot.py +0 -2
  113. investing_algorithm_framework/domain/models/risk_rules/__init__.py +7 -0
  114. investing_algorithm_framework/domain/models/risk_rules/stop_loss_rule.py +51 -0
  115. investing_algorithm_framework/domain/models/risk_rules/take_profit_rule.py +55 -0
  116. investing_algorithm_framework/domain/models/snapshot_interval.py +45 -0
  117. investing_algorithm_framework/domain/models/strategy_profile.py +19 -141
  118. investing_algorithm_framework/domain/models/time_frame.py +94 -98
  119. investing_algorithm_framework/domain/models/time_interval.py +33 -0
  120. investing_algorithm_framework/domain/models/time_unit.py +66 -2
  121. investing_algorithm_framework/domain/models/tracing/__init__.py +0 -0
  122. investing_algorithm_framework/domain/models/tracing/trace.py +23 -0
  123. investing_algorithm_framework/domain/models/trade/__init__.py +11 -0
  124. investing_algorithm_framework/domain/models/trade/trade.py +389 -0
  125. investing_algorithm_framework/domain/models/trade/trade_status.py +40 -0
  126. investing_algorithm_framework/domain/models/trade/trade_stop_loss.py +332 -0
  127. investing_algorithm_framework/domain/models/trade/trade_take_profit.py +365 -0
  128. investing_algorithm_framework/domain/order_executor.py +112 -0
  129. investing_algorithm_framework/domain/portfolio_provider.py +118 -0
  130. investing_algorithm_framework/domain/services/__init__.py +11 -0
  131. investing_algorithm_framework/domain/services/market_credential_service.py +37 -0
  132. investing_algorithm_framework/domain/services/portfolios/__init__.py +5 -0
  133. investing_algorithm_framework/domain/services/portfolios/portfolio_sync_service.py +9 -0
  134. investing_algorithm_framework/domain/services/rounding_service.py +27 -0
  135. investing_algorithm_framework/domain/services/state_handler.py +38 -0
  136. investing_algorithm_framework/domain/strategy.py +1 -29
  137. investing_algorithm_framework/domain/utils/__init__.py +15 -5
  138. investing_algorithm_framework/domain/utils/csv.py +22 -0
  139. investing_algorithm_framework/domain/utils/custom_tqdm.py +22 -0
  140. investing_algorithm_framework/domain/utils/dates.py +57 -0
  141. investing_algorithm_framework/domain/utils/jupyter_notebook_detection.py +19 -0
  142. investing_algorithm_framework/domain/utils/polars.py +53 -0
  143. investing_algorithm_framework/domain/utils/random.py +29 -0
  144. investing_algorithm_framework/download_data.py +244 -0
  145. investing_algorithm_framework/infrastructure/__init__.py +37 -11
  146. investing_algorithm_framework/infrastructure/data_providers/__init__.py +36 -0
  147. investing_algorithm_framework/infrastructure/data_providers/ccxt.py +1152 -0
  148. investing_algorithm_framework/infrastructure/data_providers/csv.py +568 -0
  149. investing_algorithm_framework/infrastructure/data_providers/pandas.py +599 -0
  150. investing_algorithm_framework/infrastructure/database/__init__.py +6 -2
  151. investing_algorithm_framework/infrastructure/database/sql_alchemy.py +86 -12
  152. investing_algorithm_framework/infrastructure/models/__init__.py +7 -3
  153. investing_algorithm_framework/infrastructure/models/order/__init__.py +2 -2
  154. investing_algorithm_framework/infrastructure/models/order/order.py +53 -53
  155. investing_algorithm_framework/infrastructure/models/order/order_metadata.py +44 -0
  156. investing_algorithm_framework/infrastructure/models/order_trade_association.py +10 -0
  157. investing_algorithm_framework/infrastructure/models/portfolio/__init__.py +1 -1
  158. investing_algorithm_framework/infrastructure/models/portfolio/portfolio_snapshot.py +8 -2
  159. investing_algorithm_framework/infrastructure/models/portfolio/{portfolio.py → sql_portfolio.py} +17 -6
  160. investing_algorithm_framework/infrastructure/models/position/position_snapshot.py +3 -1
  161. investing_algorithm_framework/infrastructure/models/trades/__init__.py +9 -0
  162. investing_algorithm_framework/infrastructure/models/trades/trade.py +130 -0
  163. investing_algorithm_framework/infrastructure/models/trades/trade_stop_loss.py +59 -0
  164. investing_algorithm_framework/infrastructure/models/trades/trade_take_profit.py +55 -0
  165. investing_algorithm_framework/infrastructure/order_executors/__init__.py +21 -0
  166. investing_algorithm_framework/infrastructure/order_executors/backtest_oder_executor.py +28 -0
  167. investing_algorithm_framework/infrastructure/order_executors/ccxt_order_executor.py +200 -0
  168. investing_algorithm_framework/infrastructure/portfolio_providers/__init__.py +19 -0
  169. investing_algorithm_framework/infrastructure/portfolio_providers/ccxt_portfolio_provider.py +199 -0
  170. investing_algorithm_framework/infrastructure/repositories/__init__.py +10 -4
  171. investing_algorithm_framework/infrastructure/repositories/order_metadata_repository.py +17 -0
  172. investing_algorithm_framework/infrastructure/repositories/order_repository.py +16 -5
  173. investing_algorithm_framework/infrastructure/repositories/portfolio_repository.py +2 -2
  174. investing_algorithm_framework/infrastructure/repositories/position_repository.py +11 -0
  175. investing_algorithm_framework/infrastructure/repositories/repository.py +84 -30
  176. investing_algorithm_framework/infrastructure/repositories/trade_repository.py +71 -0
  177. investing_algorithm_framework/infrastructure/repositories/trade_stop_loss_repository.py +29 -0
  178. investing_algorithm_framework/infrastructure/repositories/trade_take_profit_repository.py +29 -0
  179. investing_algorithm_framework/infrastructure/services/__init__.py +9 -4
  180. investing_algorithm_framework/infrastructure/services/aws/__init__.py +6 -0
  181. investing_algorithm_framework/infrastructure/services/aws/state_handler.py +193 -0
  182. investing_algorithm_framework/infrastructure/services/azure/__init__.py +5 -0
  183. investing_algorithm_framework/infrastructure/services/azure/state_handler.py +158 -0
  184. investing_algorithm_framework/infrastructure/services/backtesting/__init__.py +9 -0
  185. investing_algorithm_framework/infrastructure/services/backtesting/backtest_service.py +2596 -0
  186. investing_algorithm_framework/infrastructure/services/backtesting/event_backtest_service.py +285 -0
  187. investing_algorithm_framework/infrastructure/services/backtesting/vector_backtest_service.py +468 -0
  188. investing_algorithm_framework/services/__init__.py +123 -15
  189. investing_algorithm_framework/services/configuration_service.py +77 -11
  190. investing_algorithm_framework/services/data_providers/__init__.py +5 -0
  191. investing_algorithm_framework/services/data_providers/data_provider_service.py +1058 -0
  192. investing_algorithm_framework/services/market_credential_service.py +40 -0
  193. investing_algorithm_framework/services/metrics/__init__.py +119 -0
  194. investing_algorithm_framework/services/metrics/alpha.py +0 -0
  195. investing_algorithm_framework/services/metrics/beta.py +0 -0
  196. investing_algorithm_framework/services/metrics/cagr.py +60 -0
  197. investing_algorithm_framework/services/metrics/calmar_ratio.py +40 -0
  198. investing_algorithm_framework/services/metrics/drawdown.py +218 -0
  199. investing_algorithm_framework/services/metrics/equity_curve.py +24 -0
  200. investing_algorithm_framework/services/metrics/exposure.py +210 -0
  201. investing_algorithm_framework/services/metrics/generate.py +358 -0
  202. investing_algorithm_framework/services/metrics/mean_daily_return.py +84 -0
  203. investing_algorithm_framework/services/metrics/price_efficiency.py +57 -0
  204. investing_algorithm_framework/services/metrics/profit_factor.py +165 -0
  205. investing_algorithm_framework/services/metrics/recovery.py +113 -0
  206. investing_algorithm_framework/services/metrics/returns.py +452 -0
  207. investing_algorithm_framework/services/metrics/risk_free_rate.py +28 -0
  208. investing_algorithm_framework/services/metrics/sharpe_ratio.py +137 -0
  209. investing_algorithm_framework/services/metrics/sortino_ratio.py +74 -0
  210. investing_algorithm_framework/services/metrics/standard_deviation.py +156 -0
  211. investing_algorithm_framework/services/metrics/trades.py +473 -0
  212. investing_algorithm_framework/services/metrics/treynor_ratio.py +0 -0
  213. investing_algorithm_framework/services/metrics/ulcer.py +0 -0
  214. investing_algorithm_framework/services/metrics/value_at_risk.py +0 -0
  215. investing_algorithm_framework/services/metrics/volatility.py +118 -0
  216. investing_algorithm_framework/services/metrics/win_rate.py +177 -0
  217. investing_algorithm_framework/services/order_service/__init__.py +9 -0
  218. investing_algorithm_framework/services/order_service/order_backtest_service.py +178 -0
  219. investing_algorithm_framework/services/order_service/order_executor_lookup.py +110 -0
  220. investing_algorithm_framework/services/order_service/order_service.py +826 -0
  221. investing_algorithm_framework/services/portfolios/__init__.py +16 -0
  222. investing_algorithm_framework/services/portfolios/backtest_portfolio_service.py +54 -0
  223. investing_algorithm_framework/services/{portfolio_configuration_service.py → portfolios/portfolio_configuration_service.py} +27 -12
  224. investing_algorithm_framework/services/portfolios/portfolio_provider_lookup.py +106 -0
  225. investing_algorithm_framework/services/portfolios/portfolio_service.py +188 -0
  226. investing_algorithm_framework/services/portfolios/portfolio_snapshot_service.py +136 -0
  227. investing_algorithm_framework/services/portfolios/portfolio_sync_service.py +182 -0
  228. investing_algorithm_framework/services/positions/__init__.py +7 -0
  229. investing_algorithm_framework/services/positions/position_service.py +210 -0
  230. investing_algorithm_framework/services/repository_service.py +8 -2
  231. investing_algorithm_framework/services/trade_order_evaluator/__init__.py +9 -0
  232. investing_algorithm_framework/services/trade_order_evaluator/backtest_trade_oder_evaluator.py +117 -0
  233. investing_algorithm_framework/services/trade_order_evaluator/default_trade_order_evaluator.py +51 -0
  234. investing_algorithm_framework/services/trade_order_evaluator/trade_order_evaluator.py +80 -0
  235. investing_algorithm_framework/services/trade_service/__init__.py +9 -0
  236. investing_algorithm_framework/services/trade_service/trade_service.py +1099 -0
  237. investing_algorithm_framework/services/trade_service/trade_stop_loss_service.py +39 -0
  238. investing_algorithm_framework/services/trade_service/trade_take_profit_service.py +41 -0
  239. investing_algorithm_framework-7.25.6.dist-info/METADATA +535 -0
  240. investing_algorithm_framework-7.25.6.dist-info/RECORD +268 -0
  241. {investing_algorithm_framework-1.5.dist-info → investing_algorithm_framework-7.25.6.dist-info}/WHEEL +1 -2
  242. investing_algorithm_framework-7.25.6.dist-info/entry_points.txt +3 -0
  243. investing_algorithm_framework/app/algorithm.py +0 -630
  244. investing_algorithm_framework/domain/models/backtest_profile.py +0 -414
  245. investing_algorithm_framework/domain/models/market_data/__init__.py +0 -11
  246. investing_algorithm_framework/domain/models/market_data/asset_price.py +0 -50
  247. investing_algorithm_framework/domain/models/market_data/ohlcv.py +0 -105
  248. investing_algorithm_framework/domain/models/market_data/order_book.py +0 -63
  249. investing_algorithm_framework/domain/models/market_data/ticker.py +0 -92
  250. investing_algorithm_framework/domain/models/order/order_fee.py +0 -45
  251. investing_algorithm_framework/domain/models/trade.py +0 -78
  252. investing_algorithm_framework/domain/models/trading_data_types.py +0 -47
  253. investing_algorithm_framework/domain/models/trading_time_frame.py +0 -223
  254. investing_algorithm_framework/domain/singleton.py +0 -9
  255. investing_algorithm_framework/domain/utils/backtesting.py +0 -82
  256. investing_algorithm_framework/infrastructure/models/order/order_fee.py +0 -21
  257. investing_algorithm_framework/infrastructure/repositories/order_fee_repository.py +0 -15
  258. investing_algorithm_framework/infrastructure/services/market_backtest_service.py +0 -360
  259. investing_algorithm_framework/infrastructure/services/market_service.py +0 -410
  260. investing_algorithm_framework/infrastructure/services/performance_service.py +0 -192
  261. investing_algorithm_framework/services/backtest_service.py +0 -268
  262. investing_algorithm_framework/services/market_data_service.py +0 -77
  263. investing_algorithm_framework/services/order_backtest_service.py +0 -122
  264. investing_algorithm_framework/services/order_service.py +0 -752
  265. investing_algorithm_framework/services/portfolio_service.py +0 -164
  266. investing_algorithm_framework/services/portfolio_snapshot_service.py +0 -68
  267. investing_algorithm_framework/services/position_cost_service.py +0 -5
  268. investing_algorithm_framework/services/position_service.py +0 -63
  269. investing_algorithm_framework/services/strategy_orchestrator_service.py +0 -225
  270. investing_algorithm_framework-1.5.dist-info/AUTHORS.md +0 -8
  271. investing_algorithm_framework-1.5.dist-info/METADATA +0 -230
  272. investing_algorithm_framework-1.5.dist-info/RECORD +0 -119
  273. investing_algorithm_framework-1.5.dist-info/top_level.txt +0 -1
  274. /investing_algorithm_framework/{infrastructure/services/performance_backtest_service.py → app/reporting/tables/stop_loss_table.py} +0 -0
  275. /investing_algorithm_framework/services/{position_snapshot_service.py → positions/position_snapshot_service.py} +0 -0
  276. {investing_algorithm_framework-1.5.dist-info → investing_algorithm_framework-7.25.6.dist-info}/LICENSE +0 -0
@@ -0,0 +1,392 @@
1
+ import logging
2
+ from typing import List
3
+
4
+ from .backtest_metrics import BacktestMetrics
5
+ from .backtest_summary_metrics import BacktestSummaryMetrics
6
+
7
+ logger = logging.getLogger("investing_algorithm_framework")
8
+
9
+
10
+ def safe_weighted_mean(values, weights):
11
+ """
12
+ Calculate the weighted mean of a list of values,
13
+ ignoring None values and weights <= 0.
14
+
15
+ Args:
16
+ values (List[float | None]): List of values to average.
17
+ weights (List[float | None]): Corresponding weights for the values.
18
+
19
+ Returns:
20
+ float | None: The weighted mean, or None if no valid values.
21
+ """
22
+ vals = [(v, w) for v, w in zip(values, weights) if
23
+ v is not None and w is not None and w > 0]
24
+ if not vals:
25
+ return None
26
+ total_weight = sum(w for _, w in vals)
27
+ return sum(
28
+ v * w for v, w in vals
29
+ ) / total_weight if total_weight > 0 else None
30
+
31
+
32
+ def _compound_percentage_returns(percentages):
33
+ """
34
+ Compound percentage returns across multiple periods.
35
+
36
+ For example, if period 1 has 10% return and period 2 has 5% return,
37
+ the compounded return is: (1 + 0.10) * (1 + 0.05) - 1 = 15.5%
38
+ NOT simply 10% + 5% = 15%
39
+
40
+ Args:
41
+ percentages (List[float | None]): List of percentage returns
42
+ (as whole numbers, e.g., 10 for 10%).
43
+
44
+ Returns:
45
+ float | None: The compounded percentage return, or None if no
46
+ valid percentages.
47
+ """
48
+ valid_percentages = [p for p in percentages if p is not None]
49
+ if not valid_percentages:
50
+ return None
51
+
52
+ # Convert percentages to decimals, compound, then convert back
53
+ compounded = 1.0
54
+ for pct in valid_percentages:
55
+ compounded *= (1 + pct / 100)
56
+
57
+ # Convert back to percentage
58
+ return (compounded - 1) * 100
59
+
60
+
61
+ def combine_backtests(backtests):
62
+ """
63
+ Combine multiple backtests into a single backtest by aggregating
64
+ their results.
65
+
66
+ Args:
67
+ backtests (List[Backtest]): List of Backtest instances to combine.
68
+
69
+ Returns:
70
+ Backtest: A new Backtest instance representing the combined results.
71
+ """
72
+ backtest_metrics = []
73
+ backtest_runs = []
74
+ algorithm_id = None
75
+
76
+ for backtest in backtests:
77
+ if algorithm_id is None:
78
+ algorithm_id = backtest.algorithm_id
79
+ elif algorithm_id != backtest.algorithm_id:
80
+ raise ValueError(
81
+ "All backtests must belong to the same algorithm id"
82
+ "to be combined."
83
+ )
84
+
85
+ backtest_runs += backtest.get_all_backtest_runs()
86
+ backtest_metrics += backtest.get_all_backtest_metrics()
87
+
88
+ summary = generate_backtest_summary_metrics(backtest_metrics)
89
+
90
+ metadata = None
91
+ risk_free_rate = None
92
+
93
+ # Check if there are duplicate backtest runs
94
+ unique_date_ranges = set()
95
+ for backtest in backtests:
96
+ for run in backtest.get_all_backtest_runs():
97
+ date_range = (run.backtest_start_date, run.backtest_end_date)
98
+ if date_range in unique_date_ranges:
99
+ logger.warning(
100
+ "Duplicate backtest run detected for date range: "
101
+ f"{date_range} when combining backtests."
102
+ )
103
+ unique_date_ranges.add(date_range)
104
+
105
+ # Merge all metadata dictionaries
106
+ metadata = {}
107
+ for backtest in backtests:
108
+ if backtest.metadata:
109
+ metadata.update(backtest.metadata)
110
+
111
+ # Get the first risk-free rate
112
+ for backtest in backtests:
113
+ if backtest.risk_free_rate is not None:
114
+ risk_free_rate = backtest.risk_free_rate
115
+ break
116
+ from .backtest import Backtest
117
+
118
+ backtest = Backtest(
119
+ algorithm_id=algorithm_id,
120
+ backtest_summary=summary,
121
+ metadata=metadata,
122
+ risk_free_rate=risk_free_rate,
123
+ backtest_runs=backtest_runs
124
+ )
125
+ return backtest
126
+
127
+
128
+ def generate_backtest_summary_metrics(
129
+ backtest_metrics: List[BacktestMetrics]
130
+ ) -> BacktestSummaryMetrics:
131
+ """
132
+ Combine multiple BacktestMetrics into a single BacktestSummaryMetrics
133
+ by aggregating their results.
134
+
135
+ The aggregation logic follows these principles:
136
+ - Absolute values (gains, losses, growth): summed across periods
137
+ - Percentage returns: compounded across periods (not summed)
138
+ - Ratios (Sharpe, Sortino, etc.): weighted average by time period
139
+ - Trade-based metrics (win rate, avg trade return): weighted by trade count
140
+ - Max drawdown: worst (minimum) value across all periods
141
+ - Counts (number of trades): summed
142
+
143
+ Args:
144
+ backtest_metrics (List[BacktestMetrics]): List of BacktestMetrics
145
+ instances to combine.
146
+
147
+ Returns:
148
+ BacktestSummaryMetrics: A new BacktestSummaryMetrics instance
149
+ representing the combined results.
150
+ """
151
+ if not backtest_metrics:
152
+ return BacktestSummaryMetrics()
153
+
154
+ # Filter out None metrics
155
+ valid_metrics = [b for b in backtest_metrics if b is not None]
156
+ if not valid_metrics:
157
+ return BacktestSummaryMetrics()
158
+
159
+ # === ABSOLUTE VALUES (summed) ===
160
+ total_net_gain = sum(
161
+ b.total_net_gain for b in valid_metrics
162
+ if b.total_net_gain is not None
163
+ )
164
+ total_loss = sum(
165
+ b.gross_loss for b in valid_metrics
166
+ if b.gross_loss is not None
167
+ )
168
+ total_growth = sum(
169
+ b.total_growth for b in valid_metrics
170
+ if b.total_growth is not None
171
+ )
172
+
173
+ # === PERCENTAGE RETURNS (compounded, not summed) ===
174
+ # Compound returns: (1 + r1) * (1 + r2) * ... - 1
175
+ # For percentages stored as whole numbers (e.g., 10 for 10%)
176
+ total_net_gain_percentage = _compound_percentage_returns(
177
+ [b.total_net_gain_percentage for b in valid_metrics]
178
+ )
179
+ total_loss_percentage = _compound_percentage_returns(
180
+ [b.total_loss_percentage for b in valid_metrics]
181
+ )
182
+ total_growth_percentage = _compound_percentage_returns(
183
+ [b.total_growth_percentage for b in valid_metrics]
184
+ )
185
+
186
+ # === AVERAGES (weighted by time) ===
187
+ average_total_net_gain = safe_weighted_mean(
188
+ [b.total_net_gain for b in valid_metrics],
189
+ [b.total_number_of_days for b in valid_metrics]
190
+ )
191
+ average_total_net_gain_percentage = safe_weighted_mean(
192
+ [b.total_net_gain_percentage for b in valid_metrics],
193
+ [b.total_number_of_days for b in valid_metrics]
194
+ )
195
+ average_total_loss = safe_weighted_mean(
196
+ [b.gross_loss for b in valid_metrics],
197
+ [b.total_number_of_days for b in valid_metrics]
198
+ )
199
+ average_total_loss_percentage = safe_weighted_mean(
200
+ [b.total_loss_percentage for b in valid_metrics],
201
+ [b.total_number_of_days for b in valid_metrics]
202
+ )
203
+ average_growth = safe_weighted_mean(
204
+ [b.total_growth for b in valid_metrics],
205
+ [b.total_number_of_days for b in valid_metrics]
206
+ )
207
+ average_growth_percentage = safe_weighted_mean(
208
+ [b.total_growth_percentage for b in valid_metrics],
209
+ [b.total_number_of_days for b in valid_metrics]
210
+ )
211
+
212
+ # === RISK-ADJUSTED RATIOS (weighted by time) ===
213
+ cagr = safe_weighted_mean(
214
+ [b.cagr for b in valid_metrics],
215
+ [b.total_number_of_days for b in valid_metrics]
216
+ )
217
+ sharpe_ratio = safe_weighted_mean(
218
+ [b.sharpe_ratio for b in valid_metrics],
219
+ [b.total_number_of_days for b in valid_metrics]
220
+ )
221
+ sortino_ratio = safe_weighted_mean(
222
+ [b.sortino_ratio for b in valid_metrics],
223
+ [b.total_number_of_days for b in valid_metrics]
224
+ )
225
+ calmar_ratio = safe_weighted_mean(
226
+ [b.calmar_ratio for b in valid_metrics],
227
+ [b.total_number_of_days for b in valid_metrics]
228
+ )
229
+ annual_volatility = safe_weighted_mean(
230
+ [b.annual_volatility for b in valid_metrics],
231
+ [b.total_number_of_days for b in valid_metrics]
232
+ )
233
+
234
+ # === PROFIT FACTOR (recalculated from totals, not averaged) ===
235
+ # profit_factor = total_gross_profit / total_gross_loss
236
+ total_gross_profit = sum(
237
+ b.gross_profit for b in valid_metrics
238
+ if hasattr(b, 'gross_profit') and b.gross_profit is not None
239
+ )
240
+ total_gross_loss_abs = abs(sum(
241
+ b.gross_loss for b in valid_metrics
242
+ if b.gross_loss is not None
243
+ ))
244
+ if total_gross_loss_abs > 0:
245
+ profit_factor = total_gross_profit / total_gross_loss_abs
246
+ else:
247
+ # Fallback to weighted average if we can't calculate from totals
248
+ profit_factor = safe_weighted_mean(
249
+ [b.profit_factor for b in valid_metrics],
250
+ [b.total_number_of_days for b in valid_metrics]
251
+ )
252
+
253
+ # === MAX DRAWDOWN (worst value = minimum,
254
+ # since drawdowns are negative) ===
255
+ drawdowns = [b.max_drawdown for b in valid_metrics
256
+ if b.max_drawdown is not None]
257
+ max_drawdown = min(drawdowns) if drawdowns else None
258
+
259
+ max_drawdown_duration = max(
260
+ (b.max_drawdown_duration for b in valid_metrics
261
+ if b.max_drawdown_duration is not None), default=None
262
+ )
263
+
264
+ # === TRADE FREQUENCY (weighted by time) ===
265
+ trades_per_year = safe_weighted_mean(
266
+ [b.trades_per_year for b in valid_metrics],
267
+ [b.total_number_of_days for b in valid_metrics]
268
+ )
269
+
270
+ # === WIN RATE (weighted by number of closed trades, not time) ===
271
+ win_rate = safe_weighted_mean(
272
+ [b.win_rate for b in valid_metrics],
273
+ [b.number_of_trades_closed for b in valid_metrics]
274
+ )
275
+ current_win_rate = safe_weighted_mean(
276
+ [b.current_win_rate for b in valid_metrics],
277
+ [b.number_of_trades_closed for b in valid_metrics]
278
+ )
279
+
280
+ # === WIN/LOSS RATIO (weighted by number of closed trades) ===
281
+ win_loss_ratio = safe_weighted_mean(
282
+ [b.win_loss_ratio for b in valid_metrics],
283
+ [b.number_of_trades_closed for b in valid_metrics]
284
+ )
285
+ current_win_loss_ratio = safe_weighted_mean(
286
+ [b.current_win_loss_ratio for b in valid_metrics],
287
+ [b.number_of_trades_closed for b in valid_metrics]
288
+ )
289
+
290
+ # === TRADE COUNTS (summed) ===
291
+ number_of_trades = sum(
292
+ b.number_of_trades for b in valid_metrics
293
+ if b.number_of_trades is not None
294
+ )
295
+ number_of_trades_closed = sum(
296
+ b.number_of_trades_closed for b in valid_metrics
297
+ if b.number_of_trades_closed is not None
298
+ )
299
+
300
+ # === EXPOSURE (weighted by time) ===
301
+ cumulative_exposure = safe_weighted_mean(
302
+ [b.cumulative_exposure for b in valid_metrics],
303
+ [b.total_number_of_days for b in valid_metrics]
304
+ )
305
+ exposure_ratio = safe_weighted_mean(
306
+ [b.exposure_ratio for b in valid_metrics],
307
+ [b.total_number_of_days for b in valid_metrics]
308
+ )
309
+
310
+ # === AVERAGE TRADE RETURN (weighted by total trades) ===
311
+ average_trade_return = safe_weighted_mean(
312
+ [b.average_trade_return for b in valid_metrics],
313
+ [b.number_of_trades_closed for b in valid_metrics]
314
+ )
315
+ average_trade_return_percentage = safe_weighted_mean(
316
+ [b.average_trade_return_percentage for b in valid_metrics],
317
+ [b.number_of_trades_closed for b in valid_metrics]
318
+ )
319
+
320
+ # === AVERAGE TRADE LOSS (weighted by losing trades) ===
321
+ # We need to estimate losing trade count from win_rate if not available
322
+ losing_trade_weights = []
323
+ for b in valid_metrics:
324
+ if b.number_of_trades_closed is not None and b.win_rate is not None:
325
+ losing_trades = b.number_of_trades_closed * (1 - b.win_rate / 100)
326
+ losing_trade_weights.append(losing_trades)
327
+ else:
328
+ losing_trade_weights.append(b.number_of_trades_closed or 0)
329
+
330
+ average_trade_loss = safe_weighted_mean(
331
+ [b.average_trade_loss for b in valid_metrics],
332
+ losing_trade_weights
333
+ )
334
+ average_trade_loss_percentage = safe_weighted_mean(
335
+ [b.average_trade_loss_percentage for b in valid_metrics],
336
+ losing_trade_weights
337
+ )
338
+
339
+ # === AVERAGE TRADE GAIN (weighted by winning trades) ===
340
+ winning_trade_weights = []
341
+ for b in valid_metrics:
342
+ if b.number_of_trades_closed is not None and b.win_rate is not None:
343
+ winning_trades = b.number_of_trades_closed * (b.win_rate / 100)
344
+ winning_trade_weights.append(winning_trades)
345
+ else:
346
+ winning_trade_weights.append(b.number_of_trades_closed or 0)
347
+
348
+ average_trade_gain = safe_weighted_mean(
349
+ [b.average_trade_gain for b in valid_metrics],
350
+ winning_trade_weights
351
+ )
352
+ average_trade_gain_percentage = safe_weighted_mean(
353
+ [b.average_trade_gain_percentage for b in valid_metrics],
354
+ winning_trade_weights
355
+ )
356
+ return BacktestSummaryMetrics(
357
+ total_net_gain=total_net_gain,
358
+ total_net_gain_percentage=total_net_gain_percentage,
359
+ average_net_gain=average_total_net_gain,
360
+ average_net_gain_percentage=average_total_net_gain_percentage,
361
+ total_loss=total_loss,
362
+ total_loss_percentage=total_loss_percentage,
363
+ average_loss=average_total_loss,
364
+ average_loss_percentage=average_total_loss_percentage,
365
+ total_growth=total_growth,
366
+ total_growth_percentage=total_growth_percentage,
367
+ average_growth=average_growth,
368
+ average_growth_percentage=average_growth_percentage,
369
+ cagr=cagr,
370
+ sharpe_ratio=sharpe_ratio,
371
+ sortino_ratio=sortino_ratio,
372
+ calmar_ratio=calmar_ratio,
373
+ profit_factor=profit_factor,
374
+ annual_volatility=annual_volatility,
375
+ max_drawdown=max_drawdown,
376
+ max_drawdown_duration=max_drawdown_duration,
377
+ trades_per_year=trades_per_year,
378
+ win_rate=win_rate,
379
+ current_win_rate=current_win_rate,
380
+ win_loss_ratio=win_loss_ratio,
381
+ current_win_loss_ratio=current_win_loss_ratio,
382
+ number_of_trades=number_of_trades,
383
+ number_of_trades_closed=number_of_trades_closed,
384
+ cumulative_exposure=cumulative_exposure,
385
+ exposure_ratio=exposure_ratio,
386
+ average_trade_return=average_trade_return,
387
+ average_trade_return_percentage=average_trade_return_percentage,
388
+ average_trade_loss=average_trade_loss,
389
+ average_trade_loss_percentage=average_trade_loss_percentage,
390
+ average_trade_gain=average_trade_gain,
391
+ average_trade_gain_percentage=average_trade_gain_percentage
392
+ )
@@ -1,8 +1,6 @@
1
1
  import logging
2
- import os
3
2
  from enum import Enum
4
3
 
5
- from .constants import RESOURCE_DIRECTORY, BACKTEST_DATA_DIRECTORY_NAME
6
4
  from .exceptions import OperationalException
7
5
 
8
6
  logger = logging.getLogger("investing_algorithm_framework")
@@ -15,6 +13,7 @@ class Environment(Enum):
15
13
  DEV = 'DEV'
16
14
  PROD = 'PROD'
17
15
  TEST = 'TEST'
16
+ BACKTEST = 'BACKTEST'
18
17
 
19
18
  # Static factory method to convert
20
19
  # a string to environment
@@ -52,137 +51,61 @@ class Environment(Enum):
52
51
  return other == self.value
53
52
 
54
53
 
55
- class Config(dict):
56
- ENVIRONMENT = Environment.PROD.value
57
- LOG_LEVEL = 'DEBUG'
58
- APP_DIR = os.path.abspath(os.path.dirname(__file__))
59
- PROJECT_ROOT = os.path.abspath(os.path.join(APP_DIR, os.pardir))
60
- DEBUG_TB_INTERCEPT_REDIRECTS = False
61
- SQLALCHEMY_TRACK_MODIFICATIONS = False
62
- CACHE_TYPE = 'simple' # Can be "memcached", "redis", etc.
63
- CORS_ORIGIN_WHITELIST = [
64
- 'http://0.0.0.0:4100',
65
- 'http://localhost:4100',
66
- 'http://0.0.0.0:8000',
67
- 'http://localhost:8000',
68
- 'http://0.0.0.0:4200',
69
- 'http://localhost:4200',
70
- 'http://0.0.0.0:4000',
71
- 'http://localhost:4000',
72
- ]
73
- RESOURCE_DIRECTORY = os.getenv(RESOURCE_DIRECTORY)
74
- SCHEDULER_API_ENABLED = True
75
- CHECK_PENDING_ORDERS = True
76
- SQLITE_ENABLED = True
77
- SQLITE_INITIALIZED = False
78
- BACKTEST_DATA_DIRECTORY_NAME = "backtest_data"
79
-
80
- def __init__(self, resource_directory=None):
81
- super().__init__()
82
-
83
- if resource_directory is not None:
84
- self.RESOURCE_DIRECTORY = resource_directory
85
-
86
- super().__init__(vars(self.__class__))
87
-
88
- # def __setitem__(self, key, item):
89
- # self.__dict__[key] = item
90
- #
91
- # def __getitem__(self, key):
92
- # return self.__dict__[key]
93
- #
94
- # def __repr__(self):
95
- # return repr(self.__dict__)
96
- #
97
- # def __len__(self):
98
- # return len(self.__dict__)
99
- #
100
- # def __delitem__(self, key):
101
- # del self.__dict__[key]
102
- #
103
- # def clear(self):
104
- # return self.__dict__.clear()
105
- #
106
- # def copy(self):
107
- # return self.__dict__.copy()
108
- #
109
- # def has_key(self, k):
110
- # return k in self.__dict__
111
- #
112
- # def update(self, *args, **kwargs):
113
- # return self.__dict__.update(*args, **kwargs)
114
- #
115
- # def keys(self):
116
- # return self.__dict__.keys()
117
- #
118
- # def values(self):
119
- # return self.__dict__.values()
120
- #
121
- # def items(self):
122
- # return self.__dict__.items()
123
- #
124
- # def pop(self, *args):
125
- # return self.__dict__.pop(*args)
126
- #
127
- # def __cmp__(self, dict_):
128
- # return self.__cmp__(self.__dict__, dict_)
129
- #
130
- # def __contains__(self, item):
131
- # return item in self.__dict__
132
- #
133
- # def __iter__(self):
134
- # return iter(self.__dict__)
135
-
136
- def __str__(self):
137
- field_strings = []
138
-
139
- for attribute_key in self:
140
-
141
- if attribute_key.isupper():
142
- field_strings.append(
143
- f'{attribute_key}='
144
- f'{self[attribute_key]!r}'
145
- )
146
-
147
- return f"<{self.__class__.__name__}({','.join(field_strings)})>"
148
-
149
- def get(self, key: str, default=None):
150
- """
151
- Mimics the dict get() functionality
152
- """
153
-
154
- try:
155
- return self[key]
156
- # Ignore exception
157
- except Exception:
158
- pass
159
-
160
- return default
161
-
162
- def set(self, key: str, value) -> None:
163
- self[key] = value
164
-
165
- @staticmethod
166
- def from_dict(dictionary):
167
- config = Config()
168
-
169
- for attribute_key in dictionary:
170
-
171
- if attribute_key:
172
- config.set(attribute_key, dictionary[attribute_key])
173
- config[attribute_key] = dictionary[attribute_key]
174
-
175
- return config
176
-
177
-
178
- class TestConfig(Config):
179
- ENVIRONMENT = Environment.TEST.value
180
- TESTING = True
181
- DATABASE_CONFIG = {'DATABASE_NAME': "test"}
182
- LOG_LEVEL = "INFO"
183
-
184
-
185
- class DevConfig(Config):
186
- ENVIRONMENT = Environment.DEV.value
187
- DATABASE_CONFIG = {'DATABASE_NAME': "dev"}
188
- LOG_LEVEL = "INFO"
54
+ DEFAULT_LOGGING_CONFIG = {
55
+ 'version': 1,
56
+ 'disable_existing_loggers': False,
57
+ 'formatters': {
58
+ 'default': {
59
+ 'format': '%(asctime)s - %(name)s - %(levelname)s - %(message)s',
60
+ },
61
+ },
62
+ 'handlers': {
63
+ 'console': {
64
+ 'class': 'logging.StreamHandler',
65
+ 'formatter': 'default',
66
+ },
67
+ 'file': {
68
+ 'class': 'logging.FileHandler',
69
+ 'formatter': 'default',
70
+ 'filename': 'app_logs.log',
71
+ },
72
+ },
73
+ 'loggers': { # Make sure to add a 'loggers' section
74
+ 'investing_algorithm_framework': { # Define your logger here
75
+ 'level': 'INFO', # Set the desired level
76
+ 'handlers': ['console', 'file'], # Use these handlers
77
+ 'propagate': False,
78
+ },
79
+ },
80
+ 'root': { # Optional: Root logger configuration
81
+ 'level': 'WARNING', # Root logger defaults to WARNING
82
+ 'handlers': ['console', 'file'],
83
+ },
84
+ }
85
+
86
+ AWS_LAMBDA_LOGGING_CONFIG = {
87
+ 'version': 1,
88
+ 'disable_existing_loggers': False,
89
+ 'formatters': {
90
+ 'default': {
91
+ 'format': '%(asctime)s - %(name)s - %(levelname)s - %(message)s',
92
+ },
93
+ },
94
+ 'handlers': {
95
+ 'console': {
96
+ 'class': 'logging.StreamHandler',
97
+ 'formatter': 'default',
98
+ },
99
+ },
100
+ 'loggers': { # Make sure to add a 'loggers' section
101
+ 'investing_algorithm_framework': { # Define your logger here
102
+ 'level': 'INFO', # Set the desired level
103
+ 'handlers': ['console'], # Use these handlers
104
+ 'propagate': False,
105
+ },
106
+ },
107
+ 'root': { # Optional: Root logger configuration
108
+ 'level': 'WARNING', # Root logger defaults to WARNING
109
+ 'handlers': ['console'],
110
+ },
111
+ }
@@ -1,5 +1,4 @@
1
1
  # Framework constants
2
- FRAMEWORK_NAME = 'FRAMEWORK_NAME'
3
2
  ENVIRONMENT = "ENVIRONMENT"
4
3
  STATELESS = "STATELESS"
5
4
 
@@ -8,64 +7,46 @@ DATABASE_CONFIG = 'DATABASE_CONFIG'
8
7
  DATABASE_NAME = 'DATABASE_NAME'
9
8
  DATABASE_TYPE = 'DATABASE_TYPE'
10
9
  DATABASE_DIRECTORY_PATH = 'DATABASE_DIRECTORY_PATH'
10
+ DATABASE_DIRECTORY_NAME = 'DATABASE_DIRECTORY_NAME'
11
11
  DATABASE_URL = 'DATABASE_URL'
12
12
  DEFAULT_DATABASE_NAME = "database"
13
13
 
14
+ APPLICATION_DIRECTORY = "APP_DIR"
14
15
  RESOURCE_DIRECTORY = "RESOURCE_DIRECTORY"
15
16
  BACKTEST_DATA_DIRECTORY_NAME = "BACKTEST_DATA_DIRECTORY_NAME"
17
+ DATA_DIRECTORY = "DATA_DIRECTORY"
16
18
  LOG_LEVEL = 'LOG_LEVEL'
17
19
  BASE_DIR = 'BASE_DIR'
18
20
  SQLALCHEMY_DATABASE_URI = 'SQLALCHEMY_DATABASE_URI'
19
- SQLITE_INITIALIZED = "SQLITE_INITIALIZED"
20
21
  SQLALCHEMY_INITIALIZED = "SQLALCHEMY_INITIALIZED"
22
+ APP_MODE = "APP_MODE"
21
23
 
22
24
 
23
- BINANCE = "BINANCE"
24
-
25
- IDENTIFIER_QUERY_PARAM = "identifier"
26
- TARGET_SYMBOL_QUERY_PARAM = "target_symbol"
27
- TRADING_SYMBOL_QUERY_PARAM = "trading_symbol"
28
- ORDER_SIDE_QUERY_PARAM = "order_size"
29
- STATUS_QUERY_PARAM = "status"
30
- POSITION_SYMBOL_QUERY_PARAM = "position"
31
- SYMBOL_QUERY_PARAM = "symbol"
32
- TIME_FRAME_QUERY_PARAM = "time_frame"
33
-
34
- RESERVED_IDENTIFIERS = [
35
- BINANCE
36
- ]
37
-
38
- BINANCE_API_KEY = "binance_api_key"
39
- BINANCE_SECRET_KEY = "binance_secret_key"
40
-
41
25
  CHECK_PENDING_ORDERS = "CHECK_PENDING_ORDERS"
42
26
  RUN_STRATEGY = "RUN_STRATEGY"
43
27
 
44
28
  # Configuration
45
- TRADING_SYMBOL = "TRADING_SYMBOL"
46
- CCXT_ENABLED = "CCXT_ENABLED"
47
- API_KEY = "API_KEY"
48
- SECRET_KEY = "SECRET_KEY"
49
- MARKET = "MARKET"
50
- TRACK_PORTFOLIO_FROM = "TRACK_PORTFOLIO_FROM"
51
- SQLITE_ENABLED = "SQLITE_ENABLED"
52
- PORTFOLIOS = "PORTFOLIOS"
53
- STRATEGIES = "STRATEGIES"
54
- APPLICATION_CONFIGURED = "APPLICATION_CONFIGURED"
55
- ACTION = "ACTION"
56
-
57
29
  DEFAULT_PER_PAGE_VALUE = 10
58
30
  DEFAULT_PAGE_VALUE = 1
59
31
  ITEMIZE = 'itemize'
60
32
  ITEMIZED = 'itemized'
61
33
  PAGE = 'page'
62
34
  PER_PAGE = 'per_page'
63
-
64
- DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"
65
- DATETIME_FORMAT_BACKTESTING = "%Y-%m-%d:%H:%M"
66
- CCXT_DATETIME_FORMAT = "%Y-%m-%dT%H:%M:%S.%fZ"
35
+ DATETIME_FORMAT_BACKTESTING = "%Y-%m-%d-%H-%M"
36
+ CCXT_DATETIME_FORMAT_WITH_TIMEZONE = "%Y-%m-%dT%H:%M:%S.%fZ"
37
+ CCXT_DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S.%f"
38
+ DEFAULT_DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"
67
39
  BACKTESTING_FLAG = "BACKTESTING"
68
- BACKTESTING_INDEX_DATETIME = "BACKTESTING_INDEX_DATETIME"
40
+ INDEX_DATETIME = "INDEX_DATETIME"
41
+ LAST_SNAPSHOT_DATETIME = "LAST_SNAPSHOT_DATETIME"
69
42
  BACKTESTING_START_DATE = "BACKTESTING_START_DATE"
43
+ BACKTESTING_END_DATE = "BACKTESTING_END_DATE"
44
+ BACKTESTING_INITIAL_AMOUNT = "BACKTESTING_INITIAL_AMOUNT"
70
45
  TICKER_DATA_TYPE = "TICKER"
71
46
  OHLCV_DATA_TYPE = "OHLCV"
47
+ CURRENT_UTC_DATETIME = "CURRENT_UTC_DATETIME"
48
+ SNAPSHOT_INTERVAL = "SNAPSHOT_INTERVAL"
49
+ DATETIME_FORMAT = "DATETIME_FORMAT"
50
+ DATETIME_FORMAT_FILE_NAME = "DATETIME_FORMAT_FILE_NAME"
51
+ # Deployment
52
+ AWS_S3_STATE_BUCKET_NAME = "AWS_S3_STATE_BUCKET_NAME"