Writing a strategy
setup and on_bar, a complete example, your own helper files, and the editor.
A Talios strategy is a Python class. Two methods do the work: setup prepares your indicators once, on_bar makes a decision at the close of every bar. Here is how it all fits together.
The anatomy of a strategy
- A class deriving from Strategy, imported from the
taliospackage, in a.pyfile of your project (strategy.pyby convention). - Parameters as class attributes. Numbers, strings or booleans written at the top of the class (
rr = 3.0) are your strategy's settings: tweak one, run again. - setup(self), optional: called once per pair before the first bar, with the whole price series in
self.data. Compute your indicators here. - on_bar(self, bar), required: called at the close of every bar, oldest first. Look at what is known at that close and decide: enter, exit, move a stop, or do nothing.
A complete example
This is the demo strategy: an uptrend pullback on gold, bought during the London killzone, with a 2-ATR stop, a 3R target and a 24-bar time exit.
"""Gold trend pullback.
Long when price dips to the EMA 20 inside an EMA 100 uptrend and the next bar
closes back above it, bullish, during the London killzone. Stop 2 ATR away,
target 3R, out after 24 bars. One trade a day.
"""
from talios import Strategy, Long
from talios.indicators import atr, ema, killzone
from pullback import bullish_pullbacks, trading_day
class GoldTrendPullback(Strategy):
"""The dips of an uptrend, bought in the London morning."""
fast_len = 20
trend_len = 100
atr_len = 14
atr_mult = 2.0 # stop distance, in ATR
rr = 3.0 # target, in R
max_bars = 24 # time exit, in bars
def setup(self):
self.fast = ema(self.data.close, self.fast_len)
self.trend = ema(self.data.close, self.trend_len)
self.atr = atr(self.data, self.atr_len)
self.pullback = bullish_pullbacks(self.data, self.fast)
self.last_day = None
def on_bar(self, bar):
i = bar.i
pos = self.position
if pos:
if pos.bars(bar) >= self.max_bars:
self.exit("time")
return
if self.trend[i] is None or self.atr[i] is None:
return
if killzone(bar) != "London" or trading_day(bar) == self.last_day:
return
uptrend = self.fast[i] > self.trend[i] and bar.close > self.trend[i]
if uptrend and self.pullback[i]:
stop = bar.close - self.atr_mult * self.atr[i]
if self.enter(Long, stop=stop, rr=self.rr):
self.last_day = trading_day(bar)Your own functions, in your own files
Anything you would rather keep out of the strategy class goes in another file of the project, and is imported by its name. The demo keeps its signal logic in pullback.py:
"""Pullback signals, computed once from a pair's series."""
from datetime import timedelta
def trading_day(bar):
"""The bar's trading day: its UTC date, the Sunday evening open counted with Monday."""
day = bar.dt.date()
return day + timedelta(days=1) if day.weekday() == 6 else day
def bullish_pullbacks(data, line):
"""True at each bar closing bullish back above `line` after the bar before dipped to it."""
out = [False] * len(data)
for i in range(1, len(data)):
if line[i] is None or line[i - 1] is None:
continue
dipped = data.low[i - 1] <= line[i - 1]
out[i] = dipped and data.close[i] > line[i] and data.close[i] > data.open[i]
return out- Import by module path:
from pullback import trading_day, or from a folder,from utils.risk import atr_stop. - Read your own data files: a
.json,.csvor.txtof the project opens withopen("params.json"). - Write your own indicators as plain functions returning a list as long as the series, like the built-in ones: compute them in
setup, read them atbar.iinon_bar.
Which class runs
If the project has a strategy.py at its root, Talios starts from it; otherwise from every .py file at the root. It then picks your Strategy class. A base class that other strategies derive from is not run on its own. If several strategies are found, the one in strategy.py wins and the console tells you which one ran: keep one strategy per project, or duplicate the project for a variant.
What Python you get
- Python 3 and its standard library (math, statistics, datetime, collections, json…), plus the
taliospackage. - No numpy, no pandas, no network access, no processes, no files outside your project. The Problems tab warns you as soon as you import something that won't work.
- print() writes to the Console: the easiest way to see why a strategy takes no trade.
The editor
- Python highlighting, line numbers, Tab inserts four spaces, Tab / Shift + Tab indents or dedents a selection, and Enter keeps the indentation (one more level after a colon).
- Files the agent edited carry a green dot, and the lines it wrote a green bar in the margin.
- The file tree: New file, New folder, and a right-click menu (Open, Rename, Delete). F2 renames, Delete deletes.
- Problems. Your code is checked as you type. Syntax errors block the run and show in the Problems tab with their line; click one to jump to it. Warnings (an import that won't work, a name the package doesn't have) don't block.
Code written here
Talios only takes code written in Talios, by you or by the agent: text copied from an outside source can't be pasted into the editor (a short single line always can). Want a strategy you saw elsewhere? Describe it to the agent, and it writes it here.