algotradelib 0.0.0.9000
C++ header-only library for algorithmic trading
Loading...
Searching...
No Matches
crossover.hpp
1#pragma once
2
3#include "./signal.hpp"
4
5#include "../event.hpp"
6#include "../intent.hpp"
7
8#include <algotradelib/analytics>
9#include <algotradelib/core>
10
11#include <cstddef>
12#include <string>
13#include <utility>
14
15namespace algotradelib {
16namespace strategy {
17namespace vanilla {
18
39
49 struct Params {
53 std::size_t fast_{20};
55 std::size_t slow_{50};
61 std::string tag_{"ma-crossover"};
62 };
63
66
71 std::size_t warmup_bars() const { return params_.slow_ + 1; }
72
79 template <class Ctx>
80 void on_bar(Ctx& ctx, const BarEvent& bar) {
81 if (!(bar.instrument_ == params_.instrument_)) {
82 return;
83 }
84 if (params_.fast_ == 0 || params_.slow_ <= params_.fast_) {
85 // A fast window that is not faster would invert the signal; do nothing instead.
86 return;
87 }
88 const auto* series = ctx.bars(bar.instrument_, bar.interval_);
89 if (series == nullptr) {
90 return;
91 }
92 const auto closes = series->column(analytics::BarField::CLOSE);
93 if (static_cast<std::size_t>(closes.size()) < warmup_bars()) {
94 return;
95 }
96
97 const auto fast = line(closes, params_.fast_);
98 const auto slow = line(closes, params_.slow_);
99 const auto fast_pair = last_two(fast);
100 const auto slow_pair = last_two(slow);
101 if (!fast_pair || !slow_pair) {
102 return;
103 }
104
105 TargetPosition target;
107 target.target_quantity_ = slow_pair->current_ < fast_pair->current_ ?
109 Decimal64::parse("0");
110 target.tag_ = params_.tag_;
111 ctx.submit(target);
112 }
113
114private:
115 // The chosen average of `closes`, the whole cached series; see `AverageKind`.
116 math::Vector line(math::SeriesView closes, std::size_t span) const {
118 return exponential_line(closes, span);
119 }
120 // Only the window: slicing keeps the per-bar cost from growing with the cache. The slice is the
121 // slow window's for both lines, as it always was, so these numbers do not move.
122 return analytics::sma(closes.tail(static_cast<math::Index>(params_.slow_) + 1), span);
123 }
124};
125
130
136 params.kind_ = AverageKind::SIMPLE;
137 inner_.params_ = std::move(params);
138 }
139
141 std::size_t warmup_bars() const { return inner_.warmup_bars(); }
142
149 template <class Ctx>
150 void on_bar(Ctx& ctx, const BarEvent& bar) {
151 inner_.on_bar(ctx, bar);
152 }
153};
154
159
165 params.kind_ = AverageKind::EXPONENTIAL;
166 inner_.params_ = std::move(params);
167 }
168
170 std::size_t warmup_bars() const { return inner_.warmup_bars(); }
171
178 template <class Ctx>
179 void on_bar(Ctx& ctx, const BarEvent& bar) {
180 inner_.on_bar(ctx, bar);
181 }
182};
183
184} // namespace vanilla
185} // namespace strategy
186} // namespace algotradelib
An exact signed decimal: an int64 coefficient times 10^-scale.
Definition types.hpp:297
static Decimal64 parse(std::string_view input)
Parses a decimal string exactly (no binary floating point).
Definition types.hpp:323
The events a runner delivers to a strategy's handlers, and the market phase.
What a strategy asks the runner for: orders (OrderIntent), target positions (TargetPosition) and canc...
math::Vector sma(math::SeriesView values, std::size_t window, std::size_t min_observed)
Computes the simple moving average; identical to rolling_mean.
Definition rolling.hpp:336
Eigen::Index Index
The signed index type of rows and columns.
Definition eigen.hpp:65
Eigen::Matrix< Scalar, Eigen::Dynamic, 1 > Vector
A dense column vector of Scalar.
Definition eigen.hpp:48
Eigen::Ref< const Vector > SeriesView
A read-only reference to one series.
Definition eigen.hpp:56
The strategies this library ships (buy and hold, crossovers, mean reversion, sizing,...
math::Vector exponential_line(math::SeriesView closes, std::size_t span)
Computes the exponential moving average MovingAverageCrossover reads.
Definition signal.hpp:122
std::optional< Crossing > last_two(const math::Vector &line)
Returns the last two values of a line.
Definition signal.hpp:52
AverageKind
Which moving average MovingAverageCrossover uses.
Definition crossover.hpp:33
@ EXPONENTIAL
An exponential average with alpha = 2 / (span + 1), over every cached bar.
Definition crossover.hpp:37
@ SIMPLE
The simple mean of the window.
Definition crossover.hpp:35
What a strategy sees and emits: events, intents, the portfolio, reconciliation and risk limits.
Definition concept.hpp:16
The library: broker-neutral types (core), and the modules below.
Helpers for the vanilla strategies that compute indicators.
Identifies an instrument: its country, venue and symbol.
Definition types.hpp:78
One bar, delivered to on_bar.
Definition event.hpp:202
The position a strategy wants to hold in one instrument.
Definition intent.hpp:442
InstrumentId instrument_
The instrument.
Definition intent.hpp:444
std::string tag_
A label carried to the orders and their fills.
Definition intent.hpp:450
Decimal64 target_quantity_
The position to hold, signed: negative is short, and zero means flat.
Definition intent.hpp:446
std::size_t warmup_bars() const
Returns how many bars to load before the first live bar.
void on_bar(Ctx &ctx, const BarEvent &bar)
Calls the general crossover's on_bar.
EmaCrossover(MovingAverageCrossover::Params params={})
Constructs the strategy.
MovingAverageCrossover inner_
The general crossover, with kind_ set to EXPONENTIAL.
InstrumentId instrument_
The instrument to trade; bars for any other instrument are ignored.
Definition crossover.hpp:51
std::size_t fast_
The fast span; must be nonzero and less than slow_, or the strategy does nothing.
Definition crossover.hpp:53
Decimal64 quantity_
The shares to hold while the fast average is above the slow one.
Definition crossover.hpp:59
AverageKind kind_
Which average to use; see AverageKind.
Definition crossover.hpp:57
Holds quantity_ shares while the fast moving average is above the slow one, and is flat otherwise.
Definition crossover.hpp:47
std::size_t warmup_bars() const
Returns how many bars to load before the first live bar.
Definition crossover.hpp:71
void on_bar(Ctx &ctx, const BarEvent &bar)
States the target position for the instrument on each of its bars.
Definition crossover.hpp:80
SmaCrossover(MovingAverageCrossover::Params params={})
Constructs the strategy.
std::size_t warmup_bars() const
Returns how many bars to load before the first live bar.
MovingAverageCrossover inner_
The general crossover, with kind_ set to SIMPLE.
void on_bar(Ctx &ctx, const BarEvent &bar)
Calls the general crossover's on_bar.