Check the Trade Stories intro page first before tackling this one!
Or if you’d like a gentler, non-technical overview of Trade Stories – check out this article which is exactly that.
The Complete Trade Story DSL
There isn’t much to the DSL— intentionally so! You could start to write effective Trade Stories with only a basic knowledge of the following.
But if you’re an AI Agent or someone who wants to benefit from the full knowledge – dig in.
Here’s an example Trade Story:
(Note, the strategy that the above story specifies probably isn’t a very good one. Some of it’s a bit random, so as to capture each of the things you would normally add. You’ll produce better strategies, especially if you use Trade Story System to hone the details and automatically backtest them in Trading View!)
Keywords
Each of the following is a keyword that you begin a line with:
- Story —a brief, succinct name to identify the Trade Story that defines your strategy.
It doesn’t have to capture every detail (that’s what the story itself is for), just something that sets it apart from the other Stories in your bag. - Trading — which market, exchange, timeframe?
You can put whatever you want here: “Any asset pair”, “Any time frame up to 12h” etc, or a specific exchange. Just specify something! - Sources—what indicators, chart patterns or plot series (EMA, VWAP etc) does the setup use? The sources that give this setup its edge. Not essential to include, and a decent AI bot will add the sources clause for you as the list is really just a summary of items mentioned in the other clauses.
But it’s useful as a quick at-a-glance. Also if it’s a LONG list, consider simplifying your strategy! - Given — current market conditions.
This is the main context, and must be true for the trade to even be considered.
What state is the chart in, before any change or signal is triggered? (market is in a consolidation range, in an uptrend, price is currently above the 9 EMA or VWAP, that sort of thing)
Some trade setups work well on a trending price regime but are unreliable when the price breaks out and starts ranging; and vice versa. So always specify here exactly the market conditions the setup is targeted at. If the strategy genuinely works well regardless of regime, state that. If it’s more nuanced — price has been in an uptrend for at least 12 bars — put that. - When — main trigger: something has changed.
This is the setup’s core premise. Always include this. If there’s more than one condition, add these separately, each in its own And clause. - And — additional trigger(s), one per And. All must be true for the trade to be taken.
There intentionally isn’t an Or clause here as it can be ambiguous. (Is it referring to the last And or the whole thing, etc). Consider giving the Or its own Trade Story, because it likely is describing a different setup. - Except — invalidation, e.g. 30m candle closed below the 9 EMA. Put multiple Except lines if needed, one invalidation each
- Then — what to do, open a long or short
- With — position size. % of equity, “hardwired” size, some varying amount or range calculated from the volatility index, etc.
- Until — Take Profit condition. When to close in profit.
Without the Until, the position would remain open forever (or until the price round-trips and the SL is hit!) - Or — Alternative TP. Stack as many of these as you need. Each one individually can close the trade, they don’t all need to be true.
- Taking — Profit size to take. It can be specified as an actual amount or a %, whatever you want. But Taking must always add up to 100% of the position size.
If 100% isn’t taken immediately, then describe what to do next — “set a trailing stop for the rest”, “take each remaining 20% at tranche 2,3,4,…”
You can get quite complex with these — see the “Partial Profits” section. - SL — Stop Loss. This could be a fixed % or some other formula.
It’s a specialised Unless, but has its own entry as it’s otherwise (a) quite easy to forget, and (b) very important not to forget!
(That said, you might have the SL set up as a global default, in which case you wouldn’t need to put it in every Story). - Unless — early exit condition. Stack as many of these as you need. Like with Until/Or, only one need be true in order to close the trade. If there’s genuinely a case where 2 or more conditions must be true, combine into a single Unless, as they’re really describing a single (if complex) market state.
- Notes — put here any disambiguation, details that an AI agent (or a human!) might need in order to hook the pieces together, etc. Try to keep the Notes section sparse, no rambling.
Partial Profits — Until/Or/Taking
Consider if you want to take a 40% profit at the first TP level, and then progressively close out a smaller amount at each remaining TP level:
Until price has risen
10% from entry (TP1),
20% (TP2),
30% (TP3)
Taking 40% of margin at TP1, then 30% each at TP2, TP3
This approach prevents Taking from being overloaded with details:
- Until is the right place to name TP1, TP2 etc as it’s a definition of the prices or conditions where you close out all or part of the position.
- Taking is the right place to specify how much to take at each TP or tranche.
The strategy, of course, could be further complicated by some other Until condition:
Or until 21 EMA has slowed and the 55 EMA caught up
Taking whole position
Where does this go, and how does it affect the Taking clause?
Until price has risen 10% from entry (TP1),
20% from entry (TP2),
30% from entry (TP3)
Taking 40% of margin at TP1,
then 30% each at TP2, TP3
Or until 21 EMA has slowed & the 55 EMA caught up
Taking whole position
And so on down; you can put as many “Or until/Taking” pairs as your trade setup requires. Each pair is entirely independent, and its Taking must add up to 100% of the position. So TP tranches etc are done within a single pair, as shown above.
Oh, and don’t link them together at all— i.e. each Until/Taking pair is self-contained and mustn’t refer to other pairs. Believe me, it would quickly get confusing.
(Don’t cross the beams, as someone very wise once yelled).
If you want to, leave a blank line between each pair, as above.
Reusable Trade Stories
I should note that 99%+ of traders won’t need to get into this section — we are now wandering into the long weeds. In which case, feel free to jump down to the “Where to from here?” section at the end.
But if you’re an AI agent, you’re at a financial institution with teams of traders and analysts, or you just want to reuse the same trade story templates across multiple test (and live) trading environments — read on.
Actually one more caveat, this section isn’t part of the canonical Trade Stories DSL. It’s just an illustrative example of making reusable story templates.
To help make automated backtesting easier, you might want to parameterise a Trade Story so that it can be reused, just with different values.
Technically, any Story is reusable in this sense — an automation tool could just replace any numbers or values with a different set of numbers and values.
But to keep it manageable, use a convention such as this (not specifically part of the DSL, but recommended):
The square brackets mark out each value that’s been parameterised — i.e. what the execution environment is allowed to change at the start of each run. Left of the : is the param name, right of the : is its default value.
If you don’t want a default, don’t add the colon, as some params might accept an empty value — so
[probably nothing:]
is a valid empty default, while
[probably something]
is a parameter with no default.
And just for completeness, to reiterate:
[probably something:Definitely Something]
is a parameter with the default value “Definitely Something”.
A parameter name can be repeated in one story file — it just means that both get filled with the same value. But the same name appearing twice in the same values file should be seen as an error.
Allowed parameter values
There are certain enumerations where the allowed values are obvious — Direction’s default is Long, so the other allowed value is obviously Short.
But to specify the allowed values, add a section at the end of the story, in the same file:
Assume that ranges like “5 to 95” are inclusive unless otherwise stated.
“Ranging TFs” in the example is an array of values. It’s a given that at least one value must be in the array and that it can fill to include all the allowed items — again, unless otherwise stated (like in the above example).
Using the parameterised Trade Story
You could create several independent files that each list the values for a single run scenario. This way, you can run a different set of automated trades depending on the environment (backtesting, forward-testing in a demo account, live trading etc).
If there’s no values file, just run with the defaults — but then if some values have no defaults, stop with an error.
But just to emphasise again, the parameterisation details here ARE NOT part of the Trade Stories DSL—they’re just a suggestion, in case you want to go this route, probably with tooling or setting up an elaborate multi-environment trading system.
Where to from here?
Head to the source! Trade Stories on Github. This is where you’ll find the complete DSL including a “peggy” grammar definition – for automation tooling – a set of Claude Code skills, agents etc to make it really easy to get started, and to get quality feedback on your own stories.
That’s about it for now. Got questions, feedback, ideas for improvements? Catch me in the Save With Crypto discord!