Workspace — AI teams that work for you 24/7
Explore

skillbase/hummingbot-risk-management

Skill

Risk management for market making: P&L attribution (spread vs inventory), position limits, drawdown circuit breakers, exposure monitoring via get_portfolio_overview and search_history. Use when setting risk limits, analyzing MM P&L, monitoring portfolio exposure, or evaluating strategy risk.

SKILL.md
38
## Risk Controls in Hummingbot
39

40
Hummingbot has built-in risk controls. Use them — they are the automated last line of defense.
41

42
### Deploy-time limits (via `manage_bots`)
43

44
```
45
manage_bots(
46
  action="deploy",
47
  bot_name="...",
48
  controllers_config=["..."],
49
  max_global_drawdown_quote=500,          # stop ALL controllers if total loss > $500
50
  max_controller_drawdown_quote=200       # stop individual controller if its loss > $200
51
)
52
```
53

54
**How to size these limits:**
55
- `max_global_drawdown_quote` = maximum acceptable loss for this bot instance. Typically 5-10% of capital deployed to this bot.
56
- `max_controller_drawdown_quote` = per-strategy limit. Typically 2-5% of capital allocated to that strategy.
57

58
These are hard stops — when hit, Hummingbot automatically stops the affected controllers. This is non-negotiable: every bot deploys with both limits set.
59

60
### Strategy-level inventory controls
61

62
In controller configs (via `manage_controllers`):
63
- `inventory_skew_enabled` — widens spread on overweight side. Always enable.
64
- `inventory_target_base_pct` — target balance (50% = neutral)
65
- Order levels and amounts — implicitly limit max position
66

67
## P&L Attribution
68

69
Market making P&L must be decomposed to understand if the strategy actually works:
70

71
### Spread P&L (the intended profit)
72
```
73
spread_pnl = number_of_round_trips × effective_spread × avg_order_size
74
```
75
This should be consistently positive. If not, spreads are too tight or adverse selection is too high.
76

77
**How to calculate from MCP data:**
78
```
79
search_history(data_type="orders", status="filled", start_time=..., end_time=...)
80
```
81
Match buy fills with sell fills chronologically. Sum: (sell_price - buy_price) for matched pairs.
82

83
### Inventory P&L (the risk)
84
```
85
inventory_pnl = current_position × (current_price - avg_entry_price)
86
```
87

88
**How to calculate:**
89
```
90
get_portfolio_overview(include_balances=True)  → current position
91
get_market_data(data_type="prices", ...)       → current price
92
search_history(data_type="orders", ...)        → reconstruct avg entry from fills
93
```
94

95
### Fee drag
96
```
97
total_fees = sum of all trading fees from order history
98
```
99
Include in every P&L analysis. High-frequency MM strategies can accumulate significant fee costs.
100

101
### The critical check
102
```
103
If |inventory_pnl| > spread_pnl consistently (over 3+ days):
104
  → The strategy is speculating, not market making
105
  → Action: stop, review parameters, reduce position size
106
```
107

108
## Exposure Monitoring
109

110
### Portfolio snapshot
111
```
112
get_portfolio_overview(
113
  include_balances=True,
114
  include_perp_positions=True,
115
  include_active_orders=True,
116
  as_distribution=True          # see concentration %
117
)
118
```
119

120
### What to check
121

122
**Per-pair concentration:**
123
Any single pair > 30% of total deployed capital → over-concentrated. Reduce or diversify.
124

125
**Per-exchange concentration:**
126
Any single exchange > 40% of total capital → counterparty risk too high.
127

128
| Exchange tier | Max allocation |
129
|---|---|
130
| Top 5 by volume, regulated | Up to 40% |
131
| Top 20, established | Up to 25% |
132
| Smaller / less transparent | Up to 10% |
133
| DEX (non-custodial) | Based on smart contract audit status |
134

135
**Inventory balance per pair:**
136
```
137
get_portfolio_overview(include_balances=True)
138
```
139
Check base/quote ratio for each active pair. >70% one side for >1 hour = alert.
140

141
**Correlation risk:**
142
If running MM on ETH-USDT, SOL-USDT, and AVAX-USDT — these are all correlated with BTC. A 20% BTC drop affects ALL positions simultaneously. Treat correlated positions as one block for risk sizing.
143

144
## Stress Testing (before approving new strategy)
145

146
Calculate the impact of adverse scenarios using current portfolio data:
147

148
### Scenario 1: Flash crash (-30% in 1 hour)
149
```
150
max_loss = sum(position_size × 0.30) for all positions
151
```
152
Compare to total portfolio. If max_loss > 10% of total → reduce position sizes.
153

154
### Scenario 2: Exchange downtime (4 hours)
155
Orders sit on the book, market moves. Worst case: all orders on one side fill, market moves 10% against you.
156
```
157
exposure = sum(all_active_order_amounts)
158
max_loss = exposure × 0.10
159
```
160

161
### Scenario 3: Correlation shock
162
All crypto positions move together. Calculate total directional exposure:
163
```
164
net_exposure = sum(long_positions) - sum(short_positions)
165
max_loss_at_20pct = net_exposure × 0.20
166
```
167

168
### Scenario 4: Fee structure change
169
If maker fee doubles (exchange changes tiers), recalculate effective spread for all active strategies. Any that become negative effective spread → must stop.
170

171
## Risk Report Template
172

173
Produce periodically using MCP data:
174

175
```
176
## Risk Report: [Date]
177

178
### Data Sources
179
- Portfolio: get_portfolio_overview() at [timestamp]
180
- Recent orders: search_history(data_type="orders", last 24h)
181

182
### Portfolio Overview
183
| Metric | Value |
184
|--------|-------|
185
| Total deployed | $X |
186
| Net P&L (24h) | +/-$X |
187
|   Spread P&L | +$X |
188
|   Inventory P&L | +/-$X |
189
|   Fees | -$X |
190
| Drawdown from peak | X% |
191

192
### Exposure
193
| Exchange | Pair | Position | Exposure $ | % of total |
194
|----------|------|----------|------------|------------|
195

196
### Alerts
197
| Condition | Status | Action needed |
198
|-----------|--------|---------------|
199

200
### Stress Test
201
| Scenario | Max loss | % of portfolio |
202
|----------|----------|---------------|
203

204
### Recommendations
205
- [Specific actions]
206
```
207

208
## Incident Analysis
209

210
After any loss event or circuit breaker trigger:
211

212
1. **Timeline**: `manage_bots(action="logs", ...)` + `search_history(data_type="orders", start_time=..., end_time=...)`
213
2. **Decompose**: was the loss from inventory (market move) or from spread (adverse selection)?
214
3. **Root cause**: strategy flaw, parameter issue, market regime change, or operational failure?
215
4. **Action**: parameter adjustment, strategy redesign, or resume with no changes?
216

217
Do not restart until the analysis is complete and documented.
223
- Every bot deploys with both drawdown limits set — this is non-negotiable
224
- Decompose P&L into spread + inventory + fees — aggregate P&L hides whether the strategy works
225
- When inventory P&L consistently exceeds spread P&L, the strategy is speculating — stop immediately
226
- Counterparty limits per exchange are hard caps — no exception for "great opportunity"
227
- Correlation between positions is the hidden risk — always assess portfolio-level exposure
228
- Stress test every new strategy before deployment — calculate what happens at -30% across correlated positions
229
- After any circuit breaker trigger: full analysis before restart, no exceptions