Skip to content

Commit 829701d

Browse files
committed
docs: analyzing trades
1 parent 47fa002 commit 829701d

File tree

2 files changed

+96
-0
lines changed

2 files changed

+96
-0
lines changed

.vitepress/config.mts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ export default defineConfig({
4848
{ text: 'Running a Backtest', link: '/running-backtests' },
4949
{ text: 'Understanding the Results', link: '/understanding-results' },
5050
{ text: 'Performance Metrics', link: '/performance-metrics' },
51+
{ text: 'Trade Analysis with Tags', link: '/analyzing-trades' },
5152
]
5253
}
5354
],

analyzing-trades.md

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# Trade Analysis with Tags
2+
3+
A simple "Total Profit/Loss" number doesn't tell you *why* your strategy is performing the way it is. A profitable strategy might have one highly successful entry condition and one that consistently loses money. A losing strategy might be dragged down by a stop-loss that is too tight.
4+
5+
To solve this, Stochastix includes a powerful **Tagging** system. You can attach one or more string "tags" to every entry and exit signal. The backtesting engine then aggregates performance metrics for each tag, allowing you to perform detailed performance attribution.
6+
7+
## How to Tag Your Trades
8+
9+
The `$this->entry()` and `$this->exit()` methods in your `AbstractStrategy` both accept an optional final parameter: `enterTags` and `exitTags`, respectively. This parameter can be a single string or an array of strings.
10+
11+
Let's look at a practical example. Imagine a strategy that can enter long for two reasons: an EMA crossover or an oversold RSI. It can exit for three reasons: an opposite EMA cross (the main exit signal), a take-profit level, or a stop-loss.
12+
13+
```php
14+
// --- In onBar() ---
15+
16+
// Condition 1: EMA Crossover Entry
17+
if ($emaFast->crossesOver($emaSlow)) {
18+
$this->entry(
19+
direction: DirectionEnum::Long,
20+
orderType: OrderTypeEnum::Market,
21+
quantity: '0.5',
22+
enterTags: 'ema_cross' // Tagging the entry reason
23+
);
24+
}
25+
26+
// Condition 2: RSI Oversold Entry
27+
if ($rsi[0] < 30 && $rsi[1] >= 30) {
28+
$this->entry(
29+
direction: DirectionEnum::Long,
30+
orderType: OrderTypeEnum::Market,
31+
quantity: '0.5',
32+
enterTags: ['rsi_oversold', 'mean_reversion_signal'] // Using multiple tags
33+
);
34+
}
35+
36+
37+
// --- Exit Logic ---
38+
$openPosition = $this->orderManager->getPortfolioManager()->getOpenPosition($this->context->getCurrentSymbol());
39+
if ($openPosition) {
40+
// Exit Condition 1: Main Signal (EMA cross down)
41+
if ($emaFast->crossesUnder($emaSlow)) {
42+
$this->exit($openPosition->quantity, exitTags: 'exit_signal_cross');
43+
}
44+
45+
// Exit Condition 2: Stop-Loss (logic handled elsewhere, just showing the tag)
46+
// For example, a trailing stop might be hit.
47+
if ($shouldExitForStopLoss) {
48+
$this->exit($openPosition->quantity, exitTags: 'stop_loss');
49+
}
50+
}
51+
```
52+
53+
## Analyzing Tag Performance
54+
55+
After the backtest is complete, the `statistics` object in the results file will contain two special sections: `enterTagStats` and `exitTagStats`.
56+
57+
These sections provide a complete performance breakdown for each tag you used.
58+
59+
**Example `enterTagStats` from a results file:**
60+
61+
```json
62+
"enterTagStats": [
63+
{
64+
"label": "ema_cross",
65+
"trades": 52,
66+
"totalProfit": 1850.75,
67+
"wins": 30,
68+
"losses": 22
69+
},
70+
{
71+
"label": "rsi_oversold",
72+
"trades": 15,
73+
"totalProfit": -400.25,
74+
"wins": 4,
75+
"losses": 11
76+
}
77+
]
78+
```
79+
80+
### Answering Key Questions with Tags
81+
82+
This data allows you to answer critical questions about your strategy's logic:
83+
84+
* **"Which of my entry signals is actually profitable?"**
85+
*In the example above, trades entered because of `"ema_cross"` were highly profitable (`+1850.75`), while trades entered because of `"rsi_oversold"` were a net loss (`-400.25`). This tells you to focus on improving or removing the RSI entry condition.*
86+
87+
* **"Is my stop-loss strategy helping or hurting?"**
88+
*By analyzing the `exitTagStats` for your `'stop_loss'` tag, you can see the total P&L of all trades that were closed by it. If the total loss from stop-outs is greater than the profits preserved, your stop-loss might be too tight or poorly placed.*
89+
90+
* **"Which exit condition performs best?"**
91+
*You can compare the `averageProfitPercentage` and `totalProfit` for trades tagged with `'take_profit'` versus those with `'exit_signal_cross'` to see which exit logic captures more profit.*
92+
93+
### A Note on Multiple Tags
94+
95+
If a single trade has multiple tags (e.g., `['rsi_oversold', 'mean_reversion_signal']`), its profit and loss will be included in the statistics for **both** the `'rsi_oversold'` tag and the `'mean_reversion_signal'` tag. This is important to remember when analyzing the data, as the sum of `totalProfit` across all tags may not equal the overall total profit of the strategy if trades are multi-tagged.

0 commit comments

Comments
 (0)