deltafq 0.1.0__py3-none-any.whl → 0.1.2__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.
Potentially problematic release.
This version of deltafq might be problematic. Click here for more details.
- deltafq/__init__.py +30 -31
- deltafq/backtest/__init__.py +17 -7
- deltafq/backtest/engine.py +99 -52
- deltafq/backtest/metrics.py +113 -0
- deltafq/backtest/performance.py +81 -0
- deltafq/backtest/reporter.py +91 -0
- deltafq/core/__init__.py +19 -0
- deltafq/core/base.py +37 -0
- deltafq/core/config.py +63 -0
- deltafq/core/exceptions.py +35 -0
- deltafq/core/logger.py +46 -0
- deltafq/data/__init__.py +17 -7
- deltafq/data/cleaner.py +41 -0
- deltafq/data/fetcher.py +52 -0
- deltafq/data/storage.py +56 -0
- deltafq/data/validator.py +52 -0
- deltafq/indicators/__init__.py +17 -8
- deltafq/indicators/momentum.py +56 -23
- deltafq/indicators/technical.py +59 -0
- deltafq/indicators/trend.py +129 -61
- deltafq/indicators/volatility.py +67 -27
- deltafq/live/__init__.py +17 -0
- deltafq/live/connection.py +235 -0
- deltafq/live/data_feed.py +159 -0
- deltafq/live/monitoring.py +192 -0
- deltafq/live/risk_control.py +193 -0
- deltafq/strategy/__init__.py +17 -6
- deltafq/strategy/base_strategy.py +53 -0
- deltafq/strategy/portfolio.py +82 -0
- deltafq/strategy/risk_manager.py +64 -0
- deltafq/strategy/signal_generator.py +52 -0
- deltafq/trading/__init__.py +19 -0
- deltafq/trading/broker.py +119 -0
- deltafq/trading/execution.py +176 -0
- deltafq/trading/order_manager.py +111 -0
- deltafq/trading/position_manager.py +157 -0
- deltafq/trading/simulator.py +150 -0
- deltafq-0.1.2.dist-info/METADATA +110 -0
- deltafq-0.1.2.dist-info/RECORD +43 -0
- deltafq-0.1.2.dist-info/entry_points.txt +2 -0
- {deltafq-0.1.0.dist-info → deltafq-0.1.2.dist-info}/licenses/LICENSE +21 -22
- deltafq/backtest/result.py +0 -45
- deltafq/data/base.py +0 -30
- deltafq/data/loader.py +0 -63
- deltafq/optimization/__init__.py +0 -6
- deltafq/optimization/grid_search.py +0 -41
- deltafq/performance/__init__.py +0 -6
- deltafq/performance/metrics.py +0 -37
- deltafq/risk/__init__.py +0 -7
- deltafq/risk/metrics.py +0 -33
- deltafq/risk/position.py +0 -39
- deltafq/strategy/base.py +0 -44
- deltafq/trade/__init__.py +0 -6
- deltafq/trade/broker.py +0 -40
- deltafq/utils/__init__.py +0 -6
- deltafq/utils/time.py +0 -32
- deltafq-0.1.0.dist-info/METADATA +0 -195
- deltafq-0.1.0.dist-info/RECORD +0 -29
- {deltafq-0.1.0.dist-info → deltafq-0.1.2.dist-info}/WHEEL +0 -0
- {deltafq-0.1.0.dist-info → deltafq-0.1.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Paper trading simulator for DeltaFQ.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import pandas as pd
|
|
6
|
+
from typing import Dict, List, Optional, Any
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
from ..core.base import BaseComponent
|
|
9
|
+
from ..core.exceptions import TradingError
|
|
10
|
+
from .order_manager import OrderManager
|
|
11
|
+
from .position_manager import PositionManager
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class PaperTradingSimulator(BaseComponent):
|
|
15
|
+
"""Paper trading simulator for testing strategies."""
|
|
16
|
+
|
|
17
|
+
def __init__(self, initial_capital: float = 100000, commission: float = 0.001, **kwargs):
|
|
18
|
+
"""Initialize paper trading simulator."""
|
|
19
|
+
super().__init__(**kwargs)
|
|
20
|
+
self.initial_capital = initial_capital
|
|
21
|
+
self.commission = commission
|
|
22
|
+
self.cash = initial_capital
|
|
23
|
+
self.order_manager = OrderManager()
|
|
24
|
+
self.position_manager = PositionManager()
|
|
25
|
+
self.trades = []
|
|
26
|
+
|
|
27
|
+
def initialize(self) -> bool:
|
|
28
|
+
"""Initialize simulator."""
|
|
29
|
+
self.logger.info(f"Initializing paper trading simulator with capital: {self.initial_capital}")
|
|
30
|
+
return True
|
|
31
|
+
|
|
32
|
+
def place_order(self, symbol: str, quantity: int, order_type: str = "market",
|
|
33
|
+
price: Optional[float] = None) -> str:
|
|
34
|
+
"""Place an order."""
|
|
35
|
+
try:
|
|
36
|
+
order_id = self.order_manager.create_order(
|
|
37
|
+
symbol=symbol,
|
|
38
|
+
quantity=quantity,
|
|
39
|
+
order_type=order_type,
|
|
40
|
+
price=price
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
self.logger.info(f"Order placed: {order_id} - {symbol} {quantity} @ {order_type}")
|
|
44
|
+
return order_id
|
|
45
|
+
|
|
46
|
+
except Exception as e:
|
|
47
|
+
raise TradingError(f"Failed to place order: {str(e)}")
|
|
48
|
+
|
|
49
|
+
def execute_order(self, order_id: str, current_price: float) -> bool:
|
|
50
|
+
"""Execute an order at current price."""
|
|
51
|
+
try:
|
|
52
|
+
order = self.order_manager.get_order(order_id)
|
|
53
|
+
if not order:
|
|
54
|
+
return False
|
|
55
|
+
|
|
56
|
+
# Calculate cost
|
|
57
|
+
quantity = order['quantity']
|
|
58
|
+
cost = abs(quantity) * current_price * (1 + self.commission)
|
|
59
|
+
|
|
60
|
+
if quantity > 0: # Buy order
|
|
61
|
+
if cost <= self.cash:
|
|
62
|
+
self.cash -= cost
|
|
63
|
+
self.position_manager.add_position(symbol=order['symbol'], quantity=quantity)
|
|
64
|
+
self.trades.append({
|
|
65
|
+
'order_id': order_id,
|
|
66
|
+
'symbol': order['symbol'],
|
|
67
|
+
'quantity': quantity,
|
|
68
|
+
'price': current_price,
|
|
69
|
+
'type': 'buy',
|
|
70
|
+
'timestamp': datetime.now()
|
|
71
|
+
})
|
|
72
|
+
self.order_manager.mark_executed(order_id)
|
|
73
|
+
self.logger.info(f"Buy order executed: {order_id}")
|
|
74
|
+
return True
|
|
75
|
+
else:
|
|
76
|
+
self.logger.warning(f"Insufficient cash for order: {order_id}")
|
|
77
|
+
return False
|
|
78
|
+
else: # Sell order
|
|
79
|
+
if self.position_manager.can_sell(order['symbol'], abs(quantity)):
|
|
80
|
+
self.cash += abs(quantity) * current_price * (1 - self.commission)
|
|
81
|
+
self.position_manager.reduce_position(symbol=order['symbol'], quantity=abs(quantity))
|
|
82
|
+
self.trades.append({
|
|
83
|
+
'order_id': order_id,
|
|
84
|
+
'symbol': order['symbol'],
|
|
85
|
+
'quantity': quantity,
|
|
86
|
+
'price': current_price,
|
|
87
|
+
'type': 'sell',
|
|
88
|
+
'timestamp': datetime.now()
|
|
89
|
+
})
|
|
90
|
+
self.order_manager.mark_executed(order_id)
|
|
91
|
+
self.logger.info(f"Sell order executed: {order_id}")
|
|
92
|
+
return True
|
|
93
|
+
else:
|
|
94
|
+
self.logger.warning(f"Insufficient position for order: {order_id}")
|
|
95
|
+
return False
|
|
96
|
+
|
|
97
|
+
except Exception as e:
|
|
98
|
+
raise TradingError(f"Failed to execute order: {str(e)}")
|
|
99
|
+
|
|
100
|
+
def get_portfolio_value(self, current_prices: Dict[str, float]) -> float:
|
|
101
|
+
"""Calculate total portfolio value."""
|
|
102
|
+
total_value = self.cash
|
|
103
|
+
positions = self.position_manager.get_all_positions()
|
|
104
|
+
|
|
105
|
+
for symbol, quantity in positions.items():
|
|
106
|
+
if symbol in current_prices:
|
|
107
|
+
total_value += quantity * current_prices[symbol]
|
|
108
|
+
|
|
109
|
+
return total_value
|
|
110
|
+
|
|
111
|
+
def get_portfolio_summary(self, current_prices: Dict[str, float]) -> Dict[str, Any]:
|
|
112
|
+
"""Get portfolio summary."""
|
|
113
|
+
total_value = self.get_portfolio_value(current_prices)
|
|
114
|
+
|
|
115
|
+
return {
|
|
116
|
+
'total_value': total_value,
|
|
117
|
+
'cash': self.cash,
|
|
118
|
+
'positions': self.position_manager.get_all_positions(),
|
|
119
|
+
'total_return': (total_value - self.initial_capital) / self.initial_capital,
|
|
120
|
+
'total_trades': len(self.trades),
|
|
121
|
+
'open_orders': len(self.order_manager.get_pending_orders())
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
def run_strategy(self, strategy, data: pd.DataFrame, symbol: str = "STOCK") -> Dict[str, Any]:
|
|
125
|
+
"""Run a strategy with the simulator."""
|
|
126
|
+
self.logger.info(f"Running strategy: {strategy.name}")
|
|
127
|
+
|
|
128
|
+
for i, (date, row) in enumerate(data.iterrows()):
|
|
129
|
+
# Generate signals
|
|
130
|
+
signals = strategy.generate_signals(data.iloc[:i+1])
|
|
131
|
+
|
|
132
|
+
if not signals.empty and i > 0:
|
|
133
|
+
signal = signals.iloc[-1]
|
|
134
|
+
current_price = row['close']
|
|
135
|
+
|
|
136
|
+
# Execute trades based on signals
|
|
137
|
+
if signal > 0: # Buy signal
|
|
138
|
+
quantity = int(self.cash * 0.1 / current_price) # Use 10% of cash
|
|
139
|
+
if quantity > 0:
|
|
140
|
+
order_id = self.place_order(symbol, quantity, "market")
|
|
141
|
+
self.execute_order(order_id, current_price)
|
|
142
|
+
|
|
143
|
+
elif signal < 0: # Sell signal
|
|
144
|
+
position = self.position_manager.get_position(symbol)
|
|
145
|
+
if position > 0:
|
|
146
|
+
quantity = min(position, int(position * 0.5)) # Sell 50% of position
|
|
147
|
+
order_id = self.place_order(symbol, -quantity, "market")
|
|
148
|
+
self.execute_order(order_id, current_price)
|
|
149
|
+
|
|
150
|
+
return self.get_portfolio_summary({symbol: data['close'].iloc[-1]})
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: deltafq
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: A comprehensive Python quantitative finance library
|
|
5
|
+
Author-email: DeltaF <leek_li@outlook.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2025 DeltaF
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://github.com/Delta-F/deltafq
|
|
29
|
+
Project-URL: Repository, https://github.com/Delta-F/deltafq
|
|
30
|
+
Project-URL: Issues, https://github.com/Delta-F/deltafq/issues
|
|
31
|
+
Classifier: Development Status :: 3 - Alpha
|
|
32
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
33
|
+
Classifier: Intended Audience :: Developers
|
|
34
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
35
|
+
Classifier: Programming Language :: Python :: 3
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
40
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
41
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
42
|
+
Requires-Python: >=3.8
|
|
43
|
+
Description-Content-Type: text/markdown
|
|
44
|
+
License-File: LICENSE
|
|
45
|
+
Requires-Dist: numpy>=1.21.0
|
|
46
|
+
Requires-Dist: pandas>=1.3.0
|
|
47
|
+
Requires-Dist: scipy>=1.7.0
|
|
48
|
+
Requires-Dist: matplotlib>=3.4.0
|
|
49
|
+
Requires-Dist: seaborn>=0.11.0
|
|
50
|
+
Requires-Dist: plotly>=5.0.0
|
|
51
|
+
Requires-Dist: yfinance>=0.1.70
|
|
52
|
+
Requires-Dist: requests>=2.25.0
|
|
53
|
+
Provides-Extra: dev
|
|
54
|
+
Requires-Dist: pytest>=6.2.0; extra == "dev"
|
|
55
|
+
Requires-Dist: pytest-cov>=2.12.0; extra == "dev"
|
|
56
|
+
Requires-Dist: black>=21.0.0; extra == "dev"
|
|
57
|
+
Requires-Dist: flake8>=3.9.0; extra == "dev"
|
|
58
|
+
Requires-Dist: sphinx>=4.0.0; extra == "dev"
|
|
59
|
+
Dynamic: license-file
|
|
60
|
+
|
|
61
|
+
# DeltaFQ
|
|
62
|
+
|
|
63
|
+
A comprehensive Python quantitative finance library for strategy development, backtesting, and live trading.
|
|
64
|
+
|
|
65
|
+
## Features
|
|
66
|
+
|
|
67
|
+
- **Data Management**: Efficient data fetching, cleaning, and storage
|
|
68
|
+
- **Strategy Framework**: Flexible strategy development framework
|
|
69
|
+
- **Backtesting**: High-performance historical data backtesting
|
|
70
|
+
- **Paper Trading**: Risk-free strategy testing with simulated trading
|
|
71
|
+
- **Live Trading**: Real-time trading with broker integration
|
|
72
|
+
- **Technical Indicators**: Rich library of technical analysis indicators
|
|
73
|
+
- **Risk Management**: Built-in risk control modules
|
|
74
|
+
|
|
75
|
+
## Installation
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pip install deltafq
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Quick Start
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
import deltafq as dfq
|
|
85
|
+
|
|
86
|
+
# Fetch market data
|
|
87
|
+
data = dfq.data.fetch_stock_data('AAPL', start='2023-01-01')
|
|
88
|
+
|
|
89
|
+
# Create and test a strategy
|
|
90
|
+
strategy = dfq.strategy.MovingAverageStrategy(fast_period=10, slow_period=20)
|
|
91
|
+
results = dfq.backtest.run_backtest(strategy, data)
|
|
92
|
+
|
|
93
|
+
# Run paper trading
|
|
94
|
+
simulator = dfq.trading.PaperTradingSimulator(initial_capital=100000)
|
|
95
|
+
simulator.run_strategy(strategy, data)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Documentation
|
|
99
|
+
|
|
100
|
+
- [API Reference](docs/api_reference/)
|
|
101
|
+
- [Tutorials](docs/tutorials/)
|
|
102
|
+
- [Examples](examples/)
|
|
103
|
+
|
|
104
|
+
## Contributing
|
|
105
|
+
|
|
106
|
+
Please read our [Contributing Guide](CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests.
|
|
107
|
+
|
|
108
|
+
## License
|
|
109
|
+
|
|
110
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
deltafq/__init__.py,sha256=Ie-CZHCEWcV8lP5-yNrdr7KKAKsPmWw6ZXsAFpM6c10,509
|
|
2
|
+
deltafq/backtest/__init__.py,sha256=AzEmvcByJcs5Le2mXfQjSvRDEWaTwBktn5InwTJdyMM,314
|
|
3
|
+
deltafq/backtest/engine.py,sha256=nQyW9h_pq8qPRkpO7NmfBuTYhMUfLVMhLAAdM5xTT3I,4019
|
|
4
|
+
deltafq/backtest/metrics.py,sha256=scb1FADdTgMBFHEpgJx8nP-Fb7kewKyYDtPranubeh8,4023
|
|
5
|
+
deltafq/backtest/performance.py,sha256=LZsKqXIutIdw7mtxrP1VO1ZREzINr76yA4tTqOAeo9U,3170
|
|
6
|
+
deltafq/backtest/reporter.py,sha256=Y9WMc7Y-z0lAu_lZ6P638KLG-b3T8gZxSgJlh1NRZJ8,2968
|
|
7
|
+
deltafq/core/__init__.py,sha256=bm-EgnMOoPhOEY8mZ3aiHbHRIWcrmnPLEKqfC5-D37s,312
|
|
8
|
+
deltafq/core/base.py,sha256=YUWrSwbC4akSND4orIC5fsEZwjax54j4Y_ZcGWR2pTs,907
|
|
9
|
+
deltafq/core/config.py,sha256=zv9tr_u1YFnMsGQpAAIgJvUU8q2cL6KR00pd8Pb90bA,1780
|
|
10
|
+
deltafq/core/exceptions.py,sha256=WPOLeN7t6mRW_K7gIwSY4S4-0rILMafU5PrluSOcdRM,622
|
|
11
|
+
deltafq/core/logger.py,sha256=VsBn6z-KTUtxCqOfOc2kR3p9sKAT4oALunlbMllCyus,1234
|
|
12
|
+
deltafq/data/__init__.py,sha256=WcYwsrEaGmlE8rxcICzDYAwSig0iMGsu2u2LS7g3f4g,276
|
|
13
|
+
deltafq/data/cleaner.py,sha256=TyNmcnbhMG6VXTAP89Hm2--r07lmtBoknsg_wWfe-F8,1314
|
|
14
|
+
deltafq/data/fetcher.py,sha256=1IOFWN7YFBcKQHZTnCepzGvvCntu5C0Wi3J_E-Kz4pw,1785
|
|
15
|
+
deltafq/data/storage.py,sha256=VFc93fLoe6x6l88d4qzfrp3yMR5yaHNJ3zd2q7xJPw8,1820
|
|
16
|
+
deltafq/data/validator.py,sha256=NPB0Yt7lQ-J0UEFXY0EOtCt9Zi--Vn066PxDPQbnfhw,1763
|
|
17
|
+
deltafq/indicators/__init__.py,sha256=UcUSmlZx9eFe7dT6g2DQexsMJCqhdHtoO7jPKjLkt8s,334
|
|
18
|
+
deltafq/indicators/momentum.py,sha256=GnlWVbgZt8nJhHdLJFslZpzXDpAJ13-SdBq0rugZIqY,2032
|
|
19
|
+
deltafq/indicators/technical.py,sha256=veYOgugu8N80SGvm-vMIrdY0u4Zew1FBtba6HNRfNvM,1917
|
|
20
|
+
deltafq/indicators/trend.py,sha256=ga9FBz_5MzfN4e2QNdSED61Zpj0xzXAILb9aE4DDNy0,5088
|
|
21
|
+
deltafq/indicators/volatility.py,sha256=8ikh0-N3PTNoMMf8knEVM4zYIgGlzWlHeOor9zlcnGY,2446
|
|
22
|
+
deltafq/live/__init__.py,sha256=tFumcKEesyrK-FVSu8JwK1BttLsxfT--XS_Qqh4thTg,307
|
|
23
|
+
deltafq/live/connection.py,sha256=NAsHMl-VH2m3psoMU1IMhGE83AjUY7ZyUX_KqU_s_z8,8378
|
|
24
|
+
deltafq/live/data_feed.py,sha256=SnQrEt71iTJLm6hsZFiGOcC5fCkAFCna8_tLQ0RTuao,5627
|
|
25
|
+
deltafq/live/monitoring.py,sha256=xS065ZEfN_4s1ifwBYIxexT_NF16mld_LDO8JQdC6d0,6877
|
|
26
|
+
deltafq/live/risk_control.py,sha256=iSpVTDTObXUGiBsLIV6rks9Jj55etmZnRTk-PJjmmrk,7582
|
|
27
|
+
deltafq/strategy/__init__.py,sha256=P1HeIhCouc5kon0nB3qa2Th9cLtuy5JznzpKaNwKwTs,290
|
|
28
|
+
deltafq/strategy/base_strategy.py,sha256=0N8oCb6MB4Zkv-MXGgt2dE0dHDpD5oWIhbmyKQxhq0g,1698
|
|
29
|
+
deltafq/strategy/portfolio.py,sha256=ePju_-st5HCLRFh9tJMG5JLRg-LFNrCH8bOkjqg5QME,3061
|
|
30
|
+
deltafq/strategy/risk_manager.py,sha256=8l9VT9IFwE1Hf8-TBfMlX4EWhPUvitguT8iIXXIGb8I,2237
|
|
31
|
+
deltafq/strategy/signal_generator.py,sha256=_FJz99OpdRxZiW3D9xa2F7X1NELDb3Vtaa9M3YAYDss,2009
|
|
32
|
+
deltafq/trading/__init__.py,sha256=vBeMzD3gPRz_ehxeuqxs4lgyN0UkzjJcO-Ulyua4if0,359
|
|
33
|
+
deltafq/trading/broker.py,sha256=pgOm_2bHbKwXz77HZQ3lWUb08V60v2CzFv-RR78mKYQ,3525
|
|
34
|
+
deltafq/trading/execution.py,sha256=4OR_N8KbbfyJVtMEV_gmDkEfxYVc9ccdIIn8ZoBCLV0,6279
|
|
35
|
+
deltafq/trading/order_manager.py,sha256=nyYnPrgFmzna1q8DFAu5Q89aVwtk-opOuyBa6c09IBo,4046
|
|
36
|
+
deltafq/trading/position_manager.py,sha256=oaLnefj6AMEQQDH7qfbv8O1LybNSvW0_s2CUB1M7HpM,5997
|
|
37
|
+
deltafq/trading/simulator.py,sha256=TVffWlOFzMiOSxeqjU1egWDE2PxY7bigpFz_gp_7WAg,6464
|
|
38
|
+
deltafq-0.1.2.dist-info/licenses/LICENSE,sha256=QPPXp16UmZ3y8Ssu3T8Y74k2Tou11NloXNWeBzoPZls,1063
|
|
39
|
+
deltafq-0.1.2.dist-info/METADATA,sha256=5CaS4lYsmcZ0hlRWRC7S8yogVH0eqhAcyOkiaLqlLa4,4308
|
|
40
|
+
deltafq-0.1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
41
|
+
deltafq-0.1.2.dist-info/entry_points.txt,sha256=TVBHZfYgwrYpVZfsBonsJriXHkZm1CvBvnDW7--cxl0,45
|
|
42
|
+
deltafq-0.1.2.dist-info/top_level.txt,sha256=j1Q3ce7BEqdXVZd-mlHiJBDHq3iJGiKRKEXPW8xHLHo,8
|
|
43
|
+
deltafq-0.1.2.dist-info/RECORD,,
|
|
@@ -1,22 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
22
|
-
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 DeltaF
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
deltafq/backtest/result.py
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
"""回测结果"""
|
|
2
|
-
|
|
3
|
-
import pandas as pd
|
|
4
|
-
from typing import Dict, Any, List
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class BacktestResult:
|
|
8
|
-
"""回测结果类"""
|
|
9
|
-
|
|
10
|
-
def __init__(
|
|
11
|
-
self,
|
|
12
|
-
initial_cash: float,
|
|
13
|
-
data: pd.DataFrame,
|
|
14
|
-
signals: List[Dict]
|
|
15
|
-
):
|
|
16
|
-
self.initial_cash = initial_cash
|
|
17
|
-
self.data = data
|
|
18
|
-
self.signals = signals
|
|
19
|
-
|
|
20
|
-
def summary(self) -> Dict[str, Any]:
|
|
21
|
-
"""生成回测摘要
|
|
22
|
-
|
|
23
|
-
Returns:
|
|
24
|
-
包含各项指标的字典
|
|
25
|
-
"""
|
|
26
|
-
return {
|
|
27
|
-
'initial_cash': self.initial_cash,
|
|
28
|
-
'total_signals': len(self.signals),
|
|
29
|
-
'data_length': len(self.data),
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
def plot(self) -> None:
|
|
33
|
-
"""绘制回测结果"""
|
|
34
|
-
try:
|
|
35
|
-
import matplotlib.pyplot as plt
|
|
36
|
-
plt.figure(figsize=(12, 6))
|
|
37
|
-
plt.plot(self.data['close'])
|
|
38
|
-
plt.title('Price Chart')
|
|
39
|
-
plt.xlabel('Date')
|
|
40
|
-
plt.ylabel('Price')
|
|
41
|
-
plt.grid(True)
|
|
42
|
-
plt.show()
|
|
43
|
-
except ImportError:
|
|
44
|
-
print("需要matplotlib: pip install matplotlib")
|
|
45
|
-
|
deltafq/data/base.py
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
"""数据源基类"""
|
|
2
|
-
|
|
3
|
-
from abc import ABC, abstractmethod
|
|
4
|
-
from typing import Optional
|
|
5
|
-
import pandas as pd
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class DataSource(ABC):
|
|
9
|
-
"""数据源抽象基类"""
|
|
10
|
-
|
|
11
|
-
@abstractmethod
|
|
12
|
-
def get_data(
|
|
13
|
-
self,
|
|
14
|
-
symbol: str,
|
|
15
|
-
start_date: str,
|
|
16
|
-
end_date: str,
|
|
17
|
-
**kwargs
|
|
18
|
-
) -> pd.DataFrame:
|
|
19
|
-
"""获取数据
|
|
20
|
-
|
|
21
|
-
Args:
|
|
22
|
-
symbol: 股票代码
|
|
23
|
-
start_date: 开始日期
|
|
24
|
-
end_date: 结束日期
|
|
25
|
-
|
|
26
|
-
Returns:
|
|
27
|
-
包含OHLCV数据的DataFrame
|
|
28
|
-
"""
|
|
29
|
-
pass
|
|
30
|
-
|
deltafq/data/loader.py
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
"""数据加载器"""
|
|
2
|
-
|
|
3
|
-
import pandas as pd
|
|
4
|
-
import numpy as np
|
|
5
|
-
from typing import Optional
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def get_stock_daily(
|
|
9
|
-
symbol: str,
|
|
10
|
-
start: str,
|
|
11
|
-
end: str,
|
|
12
|
-
source: str = "mock"
|
|
13
|
-
) -> pd.DataFrame:
|
|
14
|
-
"""获取股票日线数据
|
|
15
|
-
|
|
16
|
-
Args:
|
|
17
|
-
symbol: 股票代码
|
|
18
|
-
start: 开始日期
|
|
19
|
-
end: 结束日期
|
|
20
|
-
source: 数据源,目前支持 'mock'
|
|
21
|
-
|
|
22
|
-
Returns:
|
|
23
|
-
包含OHLCV数据的DataFrame
|
|
24
|
-
"""
|
|
25
|
-
dates = pd.date_range(start=start, end=end, freq='B')
|
|
26
|
-
n = len(dates)
|
|
27
|
-
base_price = 100 + np.random.randn(n).cumsum()
|
|
28
|
-
open_price = base_price + np.random.randn(n) * 0.5
|
|
29
|
-
close_price = base_price + np.random.randn(n) * 0.5
|
|
30
|
-
high_price = np.maximum(open_price, close_price) + np.abs(np.random.randn(n) * 0.5)
|
|
31
|
-
low_price = np.minimum(open_price, close_price) - np.abs(np.random.randn(n) * 0.5)
|
|
32
|
-
|
|
33
|
-
data = pd.DataFrame({
|
|
34
|
-
'open': open_price,
|
|
35
|
-
'high': high_price,
|
|
36
|
-
'low': low_price,
|
|
37
|
-
'close': close_price,
|
|
38
|
-
'volume': np.random.randint(1000000, 10000000, n),
|
|
39
|
-
}, index=dates)
|
|
40
|
-
|
|
41
|
-
data.index.name = 'date'
|
|
42
|
-
return data
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
def get_stock_minute(
|
|
46
|
-
symbol: str,
|
|
47
|
-
start: str,
|
|
48
|
-
end: str,
|
|
49
|
-
freq: str = '1min'
|
|
50
|
-
) -> pd.DataFrame:
|
|
51
|
-
"""获取股票分钟数据
|
|
52
|
-
|
|
53
|
-
Args:
|
|
54
|
-
symbol: 股票代码
|
|
55
|
-
start: 开始日期
|
|
56
|
-
end: 结束日期
|
|
57
|
-
freq: 频率,如 '1min', '5min'
|
|
58
|
-
|
|
59
|
-
Returns:
|
|
60
|
-
包含OHLCV数据的DataFrame
|
|
61
|
-
"""
|
|
62
|
-
raise NotImplementedError("分钟数据功能待实现")
|
|
63
|
-
|
deltafq/optimization/__init__.py
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
"""网格搜索优化器"""
|
|
2
|
-
|
|
3
|
-
from typing import Dict, List, Any, Callable
|
|
4
|
-
import itertools
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class GridSearchOptimizer:
|
|
8
|
-
"""网格搜索参数优化器"""
|
|
9
|
-
|
|
10
|
-
def __init__(self):
|
|
11
|
-
self.results = []
|
|
12
|
-
|
|
13
|
-
def optimize(
|
|
14
|
-
self,
|
|
15
|
-
param_grid: Dict[str, List[Any]],
|
|
16
|
-
objective_func: Callable
|
|
17
|
-
) -> Dict[str, Any]:
|
|
18
|
-
"""执行网格搜索
|
|
19
|
-
|
|
20
|
-
Args:
|
|
21
|
-
param_grid: 参数网格
|
|
22
|
-
objective_func: 目标函数
|
|
23
|
-
|
|
24
|
-
Returns:
|
|
25
|
-
最优参数组合
|
|
26
|
-
"""
|
|
27
|
-
keys = param_grid.keys()
|
|
28
|
-
values = param_grid.values()
|
|
29
|
-
best_score = float('-inf')
|
|
30
|
-
best_params = None
|
|
31
|
-
|
|
32
|
-
for combination in itertools.product(*values):
|
|
33
|
-
params = dict(zip(keys, combination))
|
|
34
|
-
score = objective_func(params)
|
|
35
|
-
self.results.append({'params': params, 'score': score})
|
|
36
|
-
if score > best_score:
|
|
37
|
-
best_score = score
|
|
38
|
-
best_params = params
|
|
39
|
-
|
|
40
|
-
return best_params
|
|
41
|
-
|
deltafq/performance/__init__.py
DELETED
deltafq/performance/metrics.py
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
"""绩效指标计算"""
|
|
2
|
-
|
|
3
|
-
import pandas as pd
|
|
4
|
-
import numpy as np
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def calculate_annual_return(returns: pd.Series) -> float:
|
|
8
|
-
"""计算年化收益率
|
|
9
|
-
|
|
10
|
-
Args:
|
|
11
|
-
returns: 收益率序列
|
|
12
|
-
|
|
13
|
-
Returns:
|
|
14
|
-
年化收益率
|
|
15
|
-
"""
|
|
16
|
-
total_return = (1 + returns).prod() - 1
|
|
17
|
-
n_years = len(returns) / 252
|
|
18
|
-
annual_return = (1 + total_return) ** (1 / n_years) - 1
|
|
19
|
-
return annual_return
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def calculate_sharpe_ratio(
|
|
23
|
-
returns: pd.Series,
|
|
24
|
-
risk_free_rate: float = 0.03
|
|
25
|
-
) -> float:
|
|
26
|
-
"""计算夏普比率
|
|
27
|
-
|
|
28
|
-
Args:
|
|
29
|
-
returns: 收益率序列
|
|
30
|
-
risk_free_rate: 无风险利率
|
|
31
|
-
|
|
32
|
-
Returns:
|
|
33
|
-
夏普比率
|
|
34
|
-
"""
|
|
35
|
-
excess_returns = returns - risk_free_rate / 252
|
|
36
|
-
return np.sqrt(252) * excess_returns.mean() / excess_returns.std()
|
|
37
|
-
|
deltafq/risk/__init__.py
DELETED
deltafq/risk/metrics.py
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
"""风险指标计算"""
|
|
2
|
-
|
|
3
|
-
import pandas as pd
|
|
4
|
-
import numpy as np
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def calculate_max_drawdown(returns: pd.Series) -> float:
|
|
8
|
-
"""计算最大回撤
|
|
9
|
-
|
|
10
|
-
Args:
|
|
11
|
-
returns: 收益率序列
|
|
12
|
-
|
|
13
|
-
Returns:
|
|
14
|
-
最大回撤值
|
|
15
|
-
"""
|
|
16
|
-
cumulative = (1 + returns).cumprod()
|
|
17
|
-
running_max = cumulative.expanding().max()
|
|
18
|
-
drawdown = (cumulative - running_max) / running_max
|
|
19
|
-
return drawdown.min()
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def calculate_var(returns: pd.Series, confidence: float = 0.95) -> float:
|
|
23
|
-
"""计算VaR (Value at Risk)
|
|
24
|
-
|
|
25
|
-
Args:
|
|
26
|
-
returns: 收益率序列
|
|
27
|
-
confidence: 置信度
|
|
28
|
-
|
|
29
|
-
Returns:
|
|
30
|
-
VaR值
|
|
31
|
-
"""
|
|
32
|
-
return returns.quantile(1 - confidence)
|
|
33
|
-
|
deltafq/risk/position.py
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
"""仓位管理"""
|
|
2
|
-
|
|
3
|
-
from typing import Optional
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class PositionManager:
|
|
7
|
-
"""仓位管理器"""
|
|
8
|
-
|
|
9
|
-
def __init__(self, max_position: float = 1.0):
|
|
10
|
-
"""初始化仓位管理器
|
|
11
|
-
|
|
12
|
-
Args:
|
|
13
|
-
max_position: 最大持仓比例
|
|
14
|
-
"""
|
|
15
|
-
self.max_position = max_position
|
|
16
|
-
self.current_position = 0.0
|
|
17
|
-
|
|
18
|
-
def calculate_size(
|
|
19
|
-
self,
|
|
20
|
-
signal: str,
|
|
21
|
-
cash: float,
|
|
22
|
-
price: float,
|
|
23
|
-
method: str = "fixed"
|
|
24
|
-
) -> float:
|
|
25
|
-
"""计算交易数量
|
|
26
|
-
|
|
27
|
-
Args:
|
|
28
|
-
signal: 信号类型 'buy' or 'sell'
|
|
29
|
-
cash: 可用资金
|
|
30
|
-
price: 当前价格
|
|
31
|
-
method: 计算方法
|
|
32
|
-
|
|
33
|
-
Returns:
|
|
34
|
-
交易数量
|
|
35
|
-
"""
|
|
36
|
-
if method == "fixed":
|
|
37
|
-
return cash * self.max_position / price
|
|
38
|
-
return 0.0
|
|
39
|
-
|