pfund 0.0.1.dev3__tar.gz → 0.0.1.dev4__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.
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/PKG-INFO +4 -3
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/README.md +1 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/__init__.py +3 -2
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/cli/commands/config.py +4 -10
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/cli/commands/docker_compose.py +1 -1
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/cli/main.py +2 -4
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/config_handler.py +16 -5
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/engines/backtest_engine.py +1 -2
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/engines/base_engine.py +3 -2
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/mixins/backtest.py +14 -9
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/plogging/__init__.py +10 -10
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/plogging/config.py +1 -2
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pyproject.toml +11 -7
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/LICENSE +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/accounts/__init__.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/accounts/account_base.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/accounts/account_crypto.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/accounts/account_ib.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/adapter.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/balances/__init__.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/balances/balance_base.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/balances/balance_crypto.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/balances/balance_ib.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/brokers/__init__.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/brokers/broker_backtest.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/brokers/broker_base.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/brokers/broker_crypto.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/brokers/broker_live.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/brokers/ib/__init__.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/brokers/ib/broker_ib.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/brokers/ib/ib_api.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/brokers/ib/ib_client.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/brokers/ib/ib_wrapper.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/cli/__init__.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/cli/commands/__init__.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/config/bybit/config.yml +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/config/bybit/lot_sizes_inverse.yml +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/config/bybit/lot_sizes_linear.yml +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/config/bybit/lot_sizes_option.yml +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/config/bybit/lot_sizes_spot.yml +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/config/bybit/pdt_matchings_inverse.yml +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/config/bybit/pdt_matchings_linear.yml +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/config/bybit/pdt_matchings_option.yml +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/config/bybit/pdt_matchings_spot.yml +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/config/bybit/tick_sizes_inverse.yml +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/config/bybit/tick_sizes_linear.yml +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/config/bybit/tick_sizes_option.yml +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/config/bybit/tick_sizes_spot.yml +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/config/configuration.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/config/ib/config.yml +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/config/logging.yml +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/const/__init__.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/const/_zmq_routes.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/const/commons.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/const/paths.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/data_tools/data_tool_base.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/data_tools/data_tool_pandas.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/datas/__init__.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/datas/data_bar.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/datas/data_base.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/datas/data_quote.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/datas/data_tick.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/datas/data_time_based.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/datas/resolution.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/datas/timeframe.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/engines/__init__.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/engines/test_engine.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/engines/trade_engine.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/engines/train_engine.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/errors.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/exchanges/__init__.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/exchanges/bybit/__init__.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/exchanges/bybit/exchange.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/exchanges/bybit/rest_api.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/exchanges/bybit/rest_api_samples/get_markets_result_inverse +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/exchanges/bybit/rest_api_samples/get_markets_result_linear +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/exchanges/bybit/rest_api_samples/get_markets_result_option +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/exchanges/bybit/rest_api_samples/get_markets_result_spot +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/exchanges/bybit/rest_api_samples/get_markets_return_inverse +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/exchanges/bybit/rest_api_samples/get_markets_return_linear +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/exchanges/bybit/rest_api_samples/get_markets_return_option +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/exchanges/bybit/rest_api_samples/get_markets_return_spot +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/exchanges/bybit/types.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/exchanges/bybit/ws_api.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/exchanges/exchange_base.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/exchanges/rest_api_base.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/exchanges/ws_api_base.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/externals/ibapi/__init__.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/externals/ibapi/account_summary_tags.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/externals/ibapi/client.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/externals/ibapi/comm.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/externals/ibapi/commission_report.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/externals/ibapi/common.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/externals/ibapi/connection.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/externals/ibapi/contract.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/externals/ibapi/decoder.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/externals/ibapi/enum_implem.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/externals/ibapi/errors.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/externals/ibapi/execution.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/externals/ibapi/ibapi.pyproj +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/externals/ibapi/message.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/externals/ibapi/news.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/externals/ibapi/object_implem.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/externals/ibapi/order.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/externals/ibapi/order_condition.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/externals/ibapi/order_state.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/externals/ibapi/orderdecoder.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/externals/ibapi/reader.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/externals/ibapi/scanner.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/externals/ibapi/server_versions.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/externals/ibapi/softdollartier.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/externals/ibapi/tag_value.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/externals/ibapi/ticktype.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/externals/ibapi/utils.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/externals/ibapi/wrapper.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/indicators/__init__.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/indicators/indicator_base.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/indicators/ta_indicator.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/indicators/talib_indicator.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/main.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/managers/__init__.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/managers/base_manager.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/managers/connection_manager.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/managers/data_manager.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/managers/order_manager.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/managers/portfolio_manager.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/managers/risk_manager.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/managers/strategy_manager.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/models/__init__.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/models/model_backtest.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/models/model_base.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/models/model_meta.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/models/pytorch_model.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/models/sklearn_model.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/orders/__init__.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/orders/order_base.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/orders/order_crypto.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/orders/order_ib.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/orders/order_statuses.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/orders/order_time_in_force.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/plogging/filters.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/plogging/formatter.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/plogging/handlers.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/portfolio.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/positions/__init__.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/positions/position_base.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/positions/position_crypto.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/positions/position_ib.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/products/__init__.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/products/product_base.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/products/product_crypto.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/products/product_ib.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/risk_monitor.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/strategies/__init__.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/strategies/strategy_backtest.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/strategies/strategy_base.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/strategies/strategy_meta.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/utils/aliases.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/utils/envs.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/utils/utils.py +0 -0
- {pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/zeromq.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pfund
|
|
3
|
-
Version: 0.0.1.
|
|
3
|
+
Version: 0.0.1.dev4
|
|
4
4
|
Summary: A Complete Algo-Trading Framework for Machine Learning, enabling trading across TradFi, CeFi and DeFi. Supports Vectorized and Event-Driven Backtesting, Paper and Live Trading
|
|
5
5
|
Home-page: https://pfund.ai
|
|
6
6
|
License: Apache-2.0
|
|
@@ -13,9 +13,9 @@ Classifier: Programming Language :: Python :: 3
|
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.10
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.11
|
|
15
15
|
Requires-Dist: click (>=8.1.7,<9.0.0)
|
|
16
|
-
Requires-Dist: orjson (>=3.9.
|
|
16
|
+
Requires-Dist: orjson (>=3.9.14,<4.0.0)
|
|
17
17
|
Requires-Dist: pandas (>=2.2.0,<3.0.0)
|
|
18
|
-
Requires-Dist: pfeed (>=0.0.1.
|
|
18
|
+
Requires-Dist: pfeed (>=0.0.1.dev4,<0.0.2)
|
|
19
19
|
Requires-Dist: platformdirs (>=4.2.0,<5.0.0)
|
|
20
20
|
Requires-Dist: psutil (>=5.9.8,<6.0.0)
|
|
21
21
|
Requires-Dist: python-telegram-bot (>=20.7,<21.0)
|
|
@@ -33,6 +33,7 @@ Description-Content-Type: text/markdown
|
|
|
33
33
|
|
|
34
34
|
# PFund: Algo-Trading Framework for Machine Learning, TradFi, CeFi and DeFi ready.
|
|
35
35
|
|
|
36
|
+
[](https://jupyterbook.org)
|
|
36
37
|
[](https://python-poetry.org/)
|
|
37
38
|
[](https://pypi.org/project/pfund)
|
|
38
39
|

|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# PFund: Algo-Trading Framework for Machine Learning, TradFi, CeFi and DeFi ready.
|
|
2
2
|
|
|
3
|
+
[](https://jupyterbook.org)
|
|
3
4
|
[](https://python-poetry.org/)
|
|
4
5
|
[](https://pypi.org/project/pfund)
|
|
5
6
|

|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from importlib.metadata import version
|
|
2
|
+
|
|
1
3
|
from pfund.config_handler import configure
|
|
2
4
|
from pfund.engines import BacktestEngine, TrainEngine, TestEngine, TradeEngine
|
|
3
5
|
from pfund.strategies import Strategy
|
|
@@ -11,7 +13,6 @@ try:
|
|
|
11
13
|
except ImportError:
|
|
12
14
|
pass
|
|
13
15
|
from pfund.indicators import TAIndicator, TALibIndicator
|
|
14
|
-
from importlib.metadata import version
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
__version__ = version('pfund')
|
|
@@ -23,4 +24,4 @@ __all__ = (
|
|
|
23
24
|
'BacktestEngine', 'TrainEngine', 'TestEngine', 'TradeEngine',
|
|
24
25
|
'Strategy', 'Model', 'PyTorchModel', 'SKLearnModel',
|
|
25
26
|
'Feature', 'TAIndicator', 'TALibIndicator',
|
|
26
|
-
)
|
|
27
|
+
)
|
|
@@ -9,14 +9,6 @@ from pfund.const.paths import USER_CONFIG_FILE_PATH
|
|
|
9
9
|
from pfund.config_handler import ConfigHandler
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
def load_config(config_file_path: str | Path):
|
|
13
|
-
config_file_path = Path(config_file_path)
|
|
14
|
-
if config_file_path.is_file():
|
|
15
|
-
with open(config_file_path, 'r') as f:
|
|
16
|
-
return yaml.safe_load(f) or {}
|
|
17
|
-
return {}
|
|
18
|
-
|
|
19
|
-
|
|
20
12
|
def save_config(config: ConfigHandler, config_file_path: str | Path):
|
|
21
13
|
with open(config_file_path, 'w') as f:
|
|
22
14
|
yaml.dump(config.__dict__, f, default_flow_style=False)
|
|
@@ -48,14 +40,16 @@ def config(ctx, **kwargs):
|
|
|
48
40
|
if kwargs.get('list'): # Check if --list was used
|
|
49
41
|
del provided_options['list']
|
|
50
42
|
assert not provided_options, "No options should be provided with --list"
|
|
51
|
-
|
|
43
|
+
config_dict = config.__dict__
|
|
44
|
+
config_dict.update({'config_file_path': USER_CONFIG_FILE_PATH})
|
|
45
|
+
click.echo(f"PFund's config:\n{pformat(config_dict)}")
|
|
52
46
|
return
|
|
53
47
|
|
|
54
48
|
if kwargs.get('reset'): # Check if --reset was used
|
|
55
49
|
del provided_options['reset']
|
|
56
50
|
assert not provided_options, "No options should be provided with --reset"
|
|
57
51
|
remove_config(USER_CONFIG_FILE_PATH)
|
|
58
|
-
click.echo("PFund
|
|
52
|
+
click.echo("PFund's config successfully reset.")
|
|
59
53
|
return
|
|
60
54
|
|
|
61
55
|
# prints out current config if no options are provided
|
|
@@ -20,7 +20,7 @@ def docker_compose(ctx, env_file_path, docker_file_path):
|
|
|
20
20
|
if not env_file_path:
|
|
21
21
|
env_file_path = find_dotenv(usecwd=True, raise_error_if_not_found=True)
|
|
22
22
|
click.echo(f'.env file path is not specified, using env file in "{env_file_path}"')
|
|
23
|
-
load_dotenv(env_file_path)
|
|
23
|
+
load_dotenv(env_file_path, override=True)
|
|
24
24
|
if not docker_file_path:
|
|
25
25
|
package_dir = Path(importlib.resources.files(PROJ_NAME)).resolve().parents[0]
|
|
26
26
|
docker_file_path = package_dir / 'docker-compose.yml'
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import click
|
|
2
2
|
|
|
3
3
|
from pfund.config_handler import ConfigHandler
|
|
4
|
-
from pfund.const.paths import USER_CONFIG_FILE_PATH
|
|
5
4
|
from pfund.cli.commands.docker_compose import docker_compose
|
|
6
|
-
from pfund.cli.commands.config import config
|
|
5
|
+
from pfund.cli.commands.config import config
|
|
7
6
|
|
|
8
7
|
|
|
9
8
|
@click.group(context_settings={"help_option_names": ["-h", "--help"]})
|
|
@@ -12,8 +11,7 @@ from pfund.cli.commands.config import config, load_config
|
|
|
12
11
|
def pfund_group(ctx):
|
|
13
12
|
"""pfund's CLI"""
|
|
14
13
|
ctx.ensure_object(dict)
|
|
15
|
-
config
|
|
16
|
-
ctx.obj['config'] = ConfigHandler(**config)
|
|
14
|
+
ctx.obj['config'] = ConfigHandler.load_config()
|
|
17
15
|
|
|
18
16
|
|
|
19
17
|
pfund_group.add_command(docker_compose)
|
|
@@ -6,13 +6,14 @@ import logging
|
|
|
6
6
|
from types import TracebackType
|
|
7
7
|
from dataclasses import dataclass
|
|
8
8
|
|
|
9
|
+
import yaml
|
|
9
10
|
# from rich.traceback import install
|
|
10
11
|
|
|
11
|
-
from pfund.const.paths import PROJ_NAME, PROJ_PATH, LOG_PATH, PROJ_CONFIG_PATH, DATA_PATH
|
|
12
|
+
from pfund.const.paths import PROJ_NAME, PROJ_PATH, LOG_PATH, PROJ_CONFIG_PATH, DATA_PATH, USER_CONFIG_FILE_PATH
|
|
13
|
+
|
|
12
14
|
# add python path so that for files like "ibapi" (official python code from IB)
|
|
13
15
|
# can find their modules
|
|
14
16
|
sys.path.append(f'{PROJ_PATH}/externals')
|
|
15
|
-
|
|
16
17
|
# install(show_locals=False) # rich will set its own sys.excepthook
|
|
17
18
|
# rich_excepthook = sys.excepthook # get rich's excepthook
|
|
18
19
|
|
|
@@ -50,19 +51,29 @@ def import_strategies_models_features_or_indicators(path: str):
|
|
|
50
51
|
|
|
51
52
|
@dataclass
|
|
52
53
|
class ConfigHandler:
|
|
53
|
-
data_path: str = str(DATA_PATH)
|
|
54
|
+
data_path: str = str(DATA_PATH)
|
|
54
55
|
log_path: str = str(LOG_PATH)
|
|
55
56
|
logging_config_file_path: str = f'{PROJ_CONFIG_PATH}/logging.yml'
|
|
56
57
|
logging_config: dict | None = None
|
|
57
58
|
use_fork_process: bool = True
|
|
58
59
|
use_custom_excepthook: bool = True
|
|
59
60
|
|
|
61
|
+
@classmethod
|
|
62
|
+
def load_config(cls):
|
|
63
|
+
config_file_path = USER_CONFIG_FILE_PATH
|
|
64
|
+
if config_file_path.is_file():
|
|
65
|
+
with open(config_file_path, 'r') as f:
|
|
66
|
+
config = yaml.safe_load(f) or {}
|
|
67
|
+
else:
|
|
68
|
+
config = {}
|
|
69
|
+
return cls(**config)
|
|
70
|
+
|
|
60
71
|
def __post_init__(self):
|
|
61
72
|
self.logging_config = self.logging_config or {}
|
|
62
73
|
|
|
63
74
|
strategy_path, model_path = f'{self.data_path}/strategies', f'{self.data_path}/models'
|
|
64
75
|
feature_path, indicator_path = f'{self.data_path}/features', f'{self.data_path}/indicators'
|
|
65
|
-
for path in
|
|
76
|
+
for path in [strategy_path, model_path, feature_path, indicator_path]:
|
|
66
77
|
if not os.path.exists(path):
|
|
67
78
|
os.makedirs(path)
|
|
68
79
|
print(f'created {path}')
|
|
@@ -74,7 +85,7 @@ class ConfigHandler:
|
|
|
74
85
|
|
|
75
86
|
if self.use_custom_excepthook:
|
|
76
87
|
sys.excepthook = _custom_excepthook
|
|
77
|
-
|
|
88
|
+
|
|
78
89
|
|
|
79
90
|
def configure(
|
|
80
91
|
data_path: str = str(DATA_PATH),
|
|
@@ -79,8 +79,7 @@ class BacktestEngine(BaseEngine):
|
|
|
79
79
|
continue
|
|
80
80
|
if not hasattr(strategy, 'backtest'):
|
|
81
81
|
raise Exception(f'Strategy {strat} does not have backtest() method, cannot run vectorized backtesting')
|
|
82
|
-
|
|
83
|
-
strategy.backtest(df.copy(deep=True))
|
|
82
|
+
strategy.backtest()
|
|
84
83
|
elif self.mode == 'event_driven':
|
|
85
84
|
for strat, strategy in self.strategy_manager.strategies.items():
|
|
86
85
|
if strat == '_dummy':
|
|
@@ -12,6 +12,7 @@ from pfund.managers.strategy_manager import StrategyManager
|
|
|
12
12
|
from pfund.const.commons import *
|
|
13
13
|
from pfund.config_handler import ConfigHandler
|
|
14
14
|
from pfund.plogging import set_up_loggers
|
|
15
|
+
from pfund.plogging.config import LoggingDictConfigurator
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
ENV_COLORS = {
|
|
@@ -43,10 +44,10 @@ class BaseEngine(Singleton):
|
|
|
43
44
|
if not hasattr(cls, 'settings'):
|
|
44
45
|
cls.settings = settings
|
|
45
46
|
if not hasattr(cls, 'config'):
|
|
46
|
-
cls.config = config if config else ConfigHandler()
|
|
47
|
+
cls.config = config if config else ConfigHandler.load_config()
|
|
47
48
|
log_path = f'{cls.config.log_path}/{cls.env}'
|
|
48
49
|
logging_config_file_path = cls.config.logging_config_file_path
|
|
49
|
-
set_up_loggers(log_path, logging_config_file_path, user_logging_config=cls.config.logging_config)
|
|
50
|
+
cls.logging_configurator: LoggingDictConfigurator = set_up_loggers(log_path, logging_config_file_path, user_logging_config=cls.config.logging_config)
|
|
50
51
|
return super().__new__(cls)
|
|
51
52
|
|
|
52
53
|
def __init__(self, env, data_tool: DataTool='pandas', config: ConfigHandler | None=None, **settings):
|
|
@@ -12,7 +12,6 @@ if TYPE_CHECKING:
|
|
|
12
12
|
|
|
13
13
|
from pfund.managers.data_manager import get_resolutions_from_kwargs
|
|
14
14
|
from pfund.models.model_backtest import BacktestModel
|
|
15
|
-
from pfund.strategies.strategy_base import BaseStrategy
|
|
16
15
|
from pfund.models.model_base import BaseModel
|
|
17
16
|
|
|
18
17
|
|
|
@@ -25,7 +24,7 @@ class BacktestMixin:
|
|
|
25
24
|
backtest_kwargs, train_kwargs = backtest or {}, train or {}
|
|
26
25
|
|
|
27
26
|
if backtest_kwargs:
|
|
28
|
-
data_source = self._get_data_source(backtest_kwargs)
|
|
27
|
+
data_source = self._get_data_source(trading_venue, backtest_kwargs)
|
|
29
28
|
feed = self.get_feed(data_source)
|
|
30
29
|
kwargs = self._prepare_kwargs(feed, kwargs)
|
|
31
30
|
|
|
@@ -45,11 +44,15 @@ class BacktestMixin:
|
|
|
45
44
|
model = BacktestModel(type(model), model.ml_model, *model._args, **model._kwargs)
|
|
46
45
|
return super().add_model(model, name=name, model_path=model_path, is_load=is_load)
|
|
47
46
|
|
|
48
|
-
def _get_data_source(self, backtest_kwargs: dict):
|
|
47
|
+
def _get_data_source(self, trading_venue: str, backtest_kwargs: dict):
|
|
49
48
|
from pfeed.const.commons import SUPPORTED_DATA_FEEDS
|
|
49
|
+
trading_venue = trading_venue.upper()
|
|
50
|
+
# if data_source is not defined, use trading_venue as data_source
|
|
51
|
+
if trading_venue in SUPPORTED_DATA_FEEDS and 'data_source' not in backtest_kwargs:
|
|
52
|
+
backtest_kwargs['data_source'] = trading_venue
|
|
50
53
|
assert 'data_source' in backtest_kwargs, f"data_source must be defined"
|
|
51
54
|
data_source = backtest_kwargs['data_source'].upper()
|
|
52
|
-
assert
|
|
55
|
+
assert data_source in SUPPORTED_DATA_FEEDS, f"{data_source=} not in {SUPPORTED_DATA_FEEDS}"
|
|
53
56
|
return data_source
|
|
54
57
|
|
|
55
58
|
def _prepare_kwargs(self, feed: BaseFeed, kwargs: dict):
|
|
@@ -99,10 +102,12 @@ class BacktestMixin:
|
|
|
99
102
|
|
|
100
103
|
@staticmethod
|
|
101
104
|
def get_feed(data_source: str) -> BaseFeed:
|
|
102
|
-
|
|
105
|
+
from pfeed.feeds import YahooFinanceFeed, BybitFeed
|
|
103
106
|
data_source = data_source.upper()
|
|
104
107
|
if data_source == 'YAHOO_FINANCE':
|
|
105
|
-
feed =
|
|
108
|
+
feed = YahooFinanceFeed()
|
|
109
|
+
elif data_source == 'BYBIT':
|
|
110
|
+
feed = BybitFeed()
|
|
106
111
|
# TODO: other feeds
|
|
107
112
|
else:
|
|
108
113
|
raise NotImplementedError
|
|
@@ -123,9 +128,9 @@ class BacktestMixin:
|
|
|
123
128
|
continue
|
|
124
129
|
product = data.product
|
|
125
130
|
resolution = data.resolution
|
|
126
|
-
|
|
127
|
-
df = feed.get_historical_data(
|
|
128
|
-
assert not df.empty, f"dataframe is empty for {
|
|
131
|
+
pdt_or_symbol = product.symbol if feed.name == 'YAHOO_FINANCE' else product.pdt
|
|
132
|
+
df = feed.get_historical_data(pdt_or_symbol, rollback_period=rollback_period, start_date=start_date, end_date=end_date, resolution=repr(resolution), **backtest_kwargs)
|
|
133
|
+
assert not df.empty, f"dataframe is empty for {pdt_or_symbol=}"
|
|
129
134
|
df.reset_index(inplace=True)
|
|
130
135
|
latest_date = str(df['ts'][0])
|
|
131
136
|
if feed.name == 'YAHOO_FINANCE' and latest_date == utcnow_date:
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import logging
|
|
3
|
-
from pathlib import Path
|
|
4
3
|
|
|
5
4
|
from typing import Literal
|
|
6
5
|
|
|
7
6
|
from pfund.plogging.config import LoggingDictConfigurator
|
|
8
|
-
from pfund.utils.utils import load_yaml_file
|
|
7
|
+
from pfund.utils.utils import load_yaml_file, get_engine_class
|
|
9
8
|
|
|
10
9
|
|
|
11
10
|
def print_all_loggers():
|
|
@@ -14,7 +13,7 @@ def print_all_loggers():
|
|
|
14
13
|
print(name, logger, logger.handlers)
|
|
15
14
|
|
|
16
15
|
|
|
17
|
-
def set_up_loggers(log_path, logging_config_file_path, user_logging_config: dict | None=None):
|
|
16
|
+
def set_up_loggers(log_path, logging_config_file_path, user_logging_config: dict | None=None) -> LoggingDictConfigurator:
|
|
18
17
|
def deep_update(default_dict, override_dict, raise_if_key_not_exist=False):
|
|
19
18
|
'''Updates a default dictionary with an override dictionary, supports nested dictionaries.'''
|
|
20
19
|
for key, value in override_dict.items():
|
|
@@ -33,9 +32,8 @@ def set_up_loggers(log_path, logging_config_file_path, user_logging_config: dict
|
|
|
33
32
|
else:
|
|
34
33
|
# Update the key with the override value
|
|
35
34
|
default_dict[key] = value
|
|
36
|
-
print('Setting up loggers...')
|
|
37
|
-
|
|
38
|
-
if not log_path.exists():
|
|
35
|
+
# print('Setting up loggers...')
|
|
36
|
+
if not os.path.exists(log_path):
|
|
39
37
|
os.makedirs(log_path)
|
|
40
38
|
print(f'created {str(log_path)}')
|
|
41
39
|
logging_config: dict = load_yaml_file(logging_config_file_path)
|
|
@@ -43,8 +41,10 @@ def set_up_loggers(log_path, logging_config_file_path, user_logging_config: dict
|
|
|
43
41
|
deep_update(logging_config, user_logging_config)
|
|
44
42
|
logging_config['log_path'] = log_path
|
|
45
43
|
# ≈ logging.config.dictConfig(logging_config) with a custom configurator
|
|
46
|
-
LoggingDictConfigurator(logging_config)
|
|
47
|
-
|
|
44
|
+
logging_configurator = LoggingDictConfigurator(logging_config)
|
|
45
|
+
logging_configurator.configure()
|
|
46
|
+
return logging_configurator
|
|
47
|
+
|
|
48
48
|
|
|
49
49
|
# TODO: support 'feature', 'indicator'
|
|
50
50
|
def create_dynamic_logger(name: str, type_: Literal['strategy', 'model', 'manager']):
|
|
@@ -57,8 +57,8 @@ def create_dynamic_logger(name: str, type_: Literal['strategy', 'model', 'manage
|
|
|
57
57
|
assert name, "logger name cannot be empty/None"
|
|
58
58
|
assert type_ in ['strategy', 'model', 'manager'], f"Unsupported {type_=}"
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
config =
|
|
60
|
+
Engine = get_engine_class()
|
|
61
|
+
config = Engine.logging_configurator
|
|
62
62
|
|
|
63
63
|
logging_config = config.config_orig
|
|
64
64
|
loggers_config = logging_config['loggers']
|
|
@@ -4,7 +4,6 @@ import copy
|
|
|
4
4
|
import logging
|
|
5
5
|
from logging.config import DictConfigurator
|
|
6
6
|
|
|
7
|
-
from pfund.utils.utils import Singleton
|
|
8
7
|
from pfund.plogging.filters import FullPathFilter
|
|
9
8
|
from pfund.plogging.formatter import ColoredFormatter
|
|
10
9
|
|
|
@@ -19,7 +18,7 @@ LEVELS = {
|
|
|
19
18
|
|
|
20
19
|
|
|
21
20
|
# override logging's DictConfigurator as it doesn't pass in logger names to file handlers to create filenames
|
|
22
|
-
class LoggingDictConfigurator(
|
|
21
|
+
class LoggingDictConfigurator(DictConfigurator):
|
|
23
22
|
_MANUALLY_CONFIGURED_HANDLERS = [
|
|
24
23
|
'file_handler',
|
|
25
24
|
'compressed_timed_rotating_file_handler',
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "pfund"
|
|
3
|
-
version = "0.0.1.
|
|
3
|
+
version = "0.0.1.dev4"
|
|
4
4
|
description = "A Complete Algo-Trading Framework for Machine Learning, enabling trading across TradFi, CeFi and DeFi. Supports Vectorized and Event-Driven Backtesting, Paper and Live Trading"
|
|
5
5
|
license = "Apache-2.0"
|
|
6
6
|
authors = ["Stephen Yau <softwareentrepreneer+pfund@gmail.com>"]
|
|
@@ -12,11 +12,11 @@ keywords = ["trading", "algo-trading", "stocks", "cryptos", "cryptocurrencies",
|
|
|
12
12
|
|
|
13
13
|
[tool.poetry.dependencies]
|
|
14
14
|
python = "^3.10 <3.12"
|
|
15
|
-
pfeed = "^0.0.1.
|
|
15
|
+
pfeed = "^0.0.1.dev4"
|
|
16
16
|
pyzmq = "^25.1.2"
|
|
17
17
|
pyyaml = "^6.0.1"
|
|
18
18
|
psutil = "^5.9.8"
|
|
19
|
-
orjson = "^3.9.
|
|
19
|
+
orjson = "^3.9.14"
|
|
20
20
|
rich = "^13.7.0"
|
|
21
21
|
schedule = "^1.2.1"
|
|
22
22
|
websocket-client = "^1.7.0"
|
|
@@ -39,14 +39,18 @@ pfeed = {path = "../pfeed", develop = true}
|
|
|
39
39
|
pybit = "^5.6.2"
|
|
40
40
|
ta-lib = "^0.4.28"
|
|
41
41
|
pytest = "^8.0.0"
|
|
42
|
-
|
|
43
|
-
autodocsumm = {git = "https://github.com/Chilipp/autodocsumm.git"}
|
|
44
|
-
sphinxcontrib-napoleon = "^0.7"
|
|
45
|
-
pre-commit = "^3.6.0"
|
|
42
|
+
pre-commit = "^3.6.1"
|
|
46
43
|
bandit = "^1.7.7"
|
|
47
44
|
ruff = "^0.1.15"
|
|
48
45
|
pyright = "^1.1.349"
|
|
49
46
|
|
|
47
|
+
[tool.poetry.group.doc]
|
|
48
|
+
optional = true
|
|
49
|
+
|
|
50
|
+
[tool.poetry.group.doc.dependencies]
|
|
51
|
+
jupyter-book = "^1.0.0"
|
|
52
|
+
notebook = "^7.1.0"
|
|
53
|
+
|
|
50
54
|
[build-system]
|
|
51
55
|
requires = ["poetry-core"]
|
|
52
56
|
build-backend = "poetry.core.masonry.api"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/exchanges/bybit/rest_api_samples/get_markets_result_spot
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pfund-0.0.1.dev3 → pfund-0.0.1.dev4}/pfund/exchanges/bybit/rest_api_samples/get_markets_return_spot
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|