0
# Portfolio Management
1
2
Portfolio, account, and position management with real-time P&L tracking, multi-account support, comprehensive position analytics, and fund management operations. The portfolio system supports stocks, futures, bonds, and mixed asset strategies.
3
4
## Capabilities
5
6
### Position Access
7
8
Functions for accessing current positions and position details.
9
10
```python { .api }
11
def get_positions():
12
"""
13
Get all current positions.
14
15
Returns:
16
list[Position]: List of Position objects for all non-zero positions
17
"""
18
19
def get_position(order_book_id, direction=POSITION_DIRECTION.LONG):
20
"""
21
Get specific position with direction.
22
23
Parameters:
24
- order_book_id (str): Instrument identifier
25
- direction (POSITION_DIRECTION): Position direction (LONG, SHORT)
26
27
Returns:
28
Position: Position object with quantity, market_value, etc.
29
"""
30
```
31
32
### Account Operations
33
34
Functions for managing account funds and borrowing operations.
35
36
```python { .api }
37
def deposit(account_type, amount, receiving_days=0):
38
"""
39
Deposit funds to account.
40
41
Parameters:
42
- account_type (DEFAULT_ACCOUNT_TYPE): Account type (STOCK, FUTURE, BOND)
43
- amount (float): Deposit amount
44
- receiving_days (int): Days until funds are available
45
46
Returns:
47
bool: True if deposit successful
48
"""
49
50
def withdraw(account_type, amount):
51
"""
52
Withdraw funds from account.
53
54
Parameters:
55
- account_type (DEFAULT_ACCOUNT_TYPE): Account type
56
- amount (float): Withdrawal amount
57
58
Returns:
59
bool: True if withdrawal successful
60
"""
61
62
def finance(amount, account_type=DEFAULT_ACCOUNT_TYPE.STOCK):
63
"""
64
Finance/borrow funds.
65
66
Parameters:
67
- amount (float): Amount to borrow
68
- account_type (DEFAULT_ACCOUNT_TYPE): Account type for borrowing
69
70
Returns:
71
bool: True if financing successful
72
"""
73
74
def repay(amount, account_type=DEFAULT_ACCOUNT_TYPE.STOCK):
75
"""
76
Repay borrowed funds.
77
78
Parameters:
79
- amount (float): Amount to repay
80
- account_type (DEFAULT_ACCOUNT_TYPE): Account type
81
82
Returns:
83
bool: True if repayment successful
84
"""
85
```
86
87
## Portfolio Structure
88
89
The portfolio system is organized hierarchically with comprehensive tracking:
90
91
### Portfolio Object
92
93
```python { .api }
94
class Portfolio:
95
"""
96
Main portfolio container with accounts and positions.
97
98
Properties:
99
- total_value (float): Total portfolio value
100
- cash (float): Total available cash across accounts
101
- market_value (float): Total market value of positions
102
- pnl (float): Total unrealized P&L
103
- daily_pnl (float): Daily P&L change
104
- total_returns (float): Total return percentage
105
- daily_returns (float): Daily return percentage
106
- positions (dict): Dictionary of all positions keyed by instrument ID
107
- accounts (dict): Dictionary of accounts keyed by account type
108
"""
109
```
110
111
### Account Objects
112
113
```python { .api }
114
class Account:
115
"""
116
Trading account (stock/future/bond specific).
117
118
Properties:
119
- type (DEFAULT_ACCOUNT_TYPE): Account type
120
- total_value (float): Account total value
121
- cash (float): Available cash
122
- market_value (float): Market value of positions
123
- frozen_cash (float): Cash frozen in pending orders
124
- pnl (float): Unrealized P&L
125
- daily_pnl (float): Daily P&L change
126
- total_returns (float): Account total return
127
- daily_returns (float): Account daily return
128
- positions (dict): Account-specific positions
129
"""
130
```
131
132
### Position Objects
133
134
```python { .api }
135
class Position:
136
"""
137
Individual position with P&L tracking.
138
139
Properties:
140
- order_book_id (str): Instrument identifier
141
- quantity (float): Position quantity (positive=long, negative=short)
142
- market_value (float): Current market value
143
- pnl (float): Unrealized P&L
144
- daily_pnl (float): Daily P&L change
145
- avg_price (float): Average cost price
146
- last_price (float): Current market price
147
- bought_quantity (float): Total bought quantity
148
- sold_quantity (float): Total sold quantity
149
- bought_value (float): Total bought value
150
- sold_value (float): Total sold value
151
- total_orders (int): Total number of orders
152
- total_trades (int): Total number of trades
153
"""
154
```
155
156
### Futures Position Objects
157
158
```python { .api }
159
class FuturePosition:
160
"""
161
Futures position with direction-specific tracking.
162
163
Properties:
164
- buy_quantity (float): Long position quantity
165
- sell_quantity (float): Short position quantity
166
- buy_avg_price (float): Average long price
167
- sell_avg_price (float): Average short price
168
- buy_market_value (float): Long position market value
169
- sell_market_value (float): Short position market value
170
- buy_pnl (float): Long position P&L
171
- sell_pnl (float): Short position P&L
172
- margin (float): Required margin
173
- contract_multiplier (float): Contract size multiplier
174
"""
175
```
176
177
## Context Properties
178
179
Portfolio information is accessible through the strategy context:
180
181
### Context Portfolio Access
182
183
```python { .api }
184
# Available in strategy functions as context properties:
185
context.portfolio # Main Portfolio object
186
context.stock_account # Stock trading account
187
context.future_account # Futures trading account
188
context.bond_account # Bond trading account
189
190
# Portfolio properties:
191
context.portfolio.total_value # Total portfolio value
192
context.portfolio.cash # Available cash
193
context.portfolio.market_value # Market value of positions
194
context.portfolio.pnl # Unrealized P&L
195
context.portfolio.positions # All positions dict
196
197
# Account properties:
198
context.stock_account.cash # Stock account cash
199
context.stock_account.total_value # Stock account value
200
context.stock_account.positions # Stock positions
201
202
# Position access:
203
position = context.portfolio.positions["000001.XSHE"]
204
position.quantity # Position size
205
position.market_value # Position value
206
position.pnl # Position P&L
207
```
208
209
## Portfolio Management Examples
210
211
### Basic Portfolio Monitoring
212
213
```python
214
def handle_bar(context, bar_dict):
215
# Portfolio overview
216
total_value = context.portfolio.total_value
217
cash = context.portfolio.cash
218
market_value = context.portfolio.market_value
219
220
# Check if portfolio is profitable
221
if context.portfolio.pnl > 0:
222
logger.info(f"Portfolio profit: {context.portfolio.pnl:.2f}")
223
224
# Account-specific information
225
stock_cash = context.stock_account.cash
226
stock_positions = len(context.stock_account.positions)
227
228
logger.info(f"Portfolio value: {total_value:.2f}, Cash: {cash:.2f}")
229
logger.info(f"Stock positions: {stock_positions}")
230
```
231
232
### Position Management
233
234
```python
235
def handle_bar(context, bar_dict):
236
# Get all positions
237
positions = get_positions()
238
239
for position in positions:
240
stock = position.order_book_id
241
quantity = position.quantity
242
pnl = position.pnl
243
244
# Check position P&L
245
if pnl < -1000: # Stop loss at -1000
246
order_target_percent(stock, 0) # Close position
247
logger.info(f"Stop loss triggered for {stock}")
248
249
# Position sizing check
250
position_weight = position.market_value / context.portfolio.total_value
251
if position_weight > 0.1: # Max 10% per position
252
target_value = context.portfolio.total_value * 0.1
253
order_target_value(stock, target_value)
254
```
255
256
### Risk Management
257
258
```python
259
def handle_bar(context, bar_dict):
260
# Portfolio risk metrics
261
total_value = context.portfolio.total_value
262
daily_return = context.portfolio.daily_returns
263
264
# Maximum drawdown check
265
if not hasattr(context, 'peak_value'):
266
context.peak_value = total_value
267
else:
268
context.peak_value = max(context.peak_value, total_value)
269
270
drawdown = (context.peak_value - total_value) / context.peak_value
271
272
if drawdown > 0.1: # 10% max drawdown
273
# Reduce positions
274
for position in get_positions():
275
current_weight = position.market_value / total_value
276
new_weight = current_weight * 0.5 # Halve positions
277
order_target_percent(position.order_book_id, new_weight)
278
279
logger.warning(f"Drawdown limit reached: {drawdown:.2%}")
280
```
281
282
### Multi-Account Management
283
284
```python
285
def handle_bar(context, bar_dict):
286
# Stock account management
287
if context.stock_account.cash < 10000:
288
# Transfer funds from futures account
289
if context.future_account.cash > 20000:
290
withdraw(DEFAULT_ACCOUNT_TYPE.FUTURE, 10000)
291
deposit(DEFAULT_ACCOUNT_TYPE.STOCK, 10000)
292
293
# Futures account margin check
294
total_margin = sum(pos.margin for pos in context.future_account.positions.values())
295
available_margin = context.future_account.cash - total_margin
296
297
if available_margin < 5000: # Maintain minimum margin
298
logger.warning("Low margin available in futures account")
299
```
300
301
### Performance Tracking
302
303
```python
304
def after_trading(context):
305
# Daily performance summary
306
portfolio = context.portfolio
307
308
performance_data = {
309
"date": context.now.date(),
310
"total_value": portfolio.total_value,
311
"cash": portfolio.cash,
312
"market_value": portfolio.market_value,
313
"daily_pnl": portfolio.daily_pnl,
314
"daily_return": portfolio.daily_returns,
315
"total_return": portfolio.total_returns,
316
"position_count": len(get_positions())
317
}
318
319
# Store performance data
320
if not hasattr(context, 'performance_history'):
321
context.performance_history = []
322
323
context.performance_history.append(performance_data)
324
325
# Log daily summary
326
logger.info(f"Daily P&L: {portfolio.daily_pnl:.2f}")
327
logger.info(f"Daily Return: {portfolio.daily_returns:.2%}")
328
logger.info(f"Total Return: {portfolio.total_returns:.2%}")
329
```
330
331
### Cash Management
332
333
```python
334
def handle_bar(context, bar_dict):
335
# Maintain minimum cash levels
336
min_cash_ratio = 0.05 # 5% minimum cash
337
current_cash_ratio = context.portfolio.cash / context.portfolio.total_value
338
339
if current_cash_ratio < min_cash_ratio:
340
# Sell some positions to raise cash
341
positions = get_positions()
342
if positions:
343
# Sell smallest position first
344
smallest_position = min(positions, key=lambda p: p.market_value)
345
order_target_percent(smallest_position.order_book_id, 0)
346
logger.info(f"Selling {smallest_position.order_book_id} to raise cash")
347
348
# Invest excess cash
349
elif current_cash_ratio > 0.2: # More than 20% cash
350
# Find underweight positions to invest in
351
for stock in context.universe:
352
current_weight = 0
353
if stock in context.portfolio.positions:
354
pos_value = context.portfolio.positions[stock].market_value
355
current_weight = pos_value / context.portfolio.total_value
356
357
target_weight = 1.0 / len(context.universe) # Equal weight
358
if current_weight < target_weight * 0.8: # 20% underweight
359
order_target_percent(stock, target_weight)
360
break
361
```