algotradelib 0.0.0.9000
C++ header-only library for algorithmic trading
Loading...
Searching...
No Matches
signal.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <algotradelib/analytics>
4
5#include <cstddef>
6#include <optional>
7#include <stdexcept>
8
9namespace algotradelib {
10namespace strategy {
11namespace vanilla {
12
19
21struct Crossing {
26
32 bool rose_above(const Crossing& other) const {
33 return previous_ <= other.previous_ && other.current_ < current_;
34 }
35
41 bool fell_below(const Crossing& other) const {
42 return other.previous_ <= previous_ && current_ < other.current_;
43 }
44};
45
52inline std::optional<Crossing> last_two(const math::Vector& line) {
53 if (line.size() < 2) {
54 return std::nullopt;
55 }
56 const Crossing pair{line[line.size() - 2], line[line.size() - 1]};
57 if (!math::observed(pair.previous_) || !math::observed(pair.current_)) {
58 return std::nullopt;
59 }
60 return pair;
61}
62
82inline math::Vector adjusted_ema(math::SeriesView values, math::Scalar alpha, std::size_t min_observed = 1) {
83 if (!(math::Scalar{0} < alpha && alpha <= math::Scalar{1})) {
84 throw std::invalid_argument("an ema smoothing factor must be in (0, 1]");
85 }
86 if (min_observed == 0) {
87 throw std::invalid_argument("ema must require at least one observation");
88 }
89 math::Vector result = math::unobserved(static_cast<std::size_t>(values.size()));
90 const math::Scalar keep = math::Scalar{1} - alpha;
91 math::Scalar mean{0};
92 math::Scalar total{0};
93 std::size_t count = 0;
94 for (math::Index row = 0; row < values.size(); ++row) {
95 const math::Scalar value = values[row];
96 if (!math::observed(value)) {
97 continue;
98 }
99 total = math::Scalar{1} + keep * total;
100 // `alpha = 1` keeps only the newest value, exactly: `mean + (value - mean)` need not round back to it.
101 mean = count == 0 || keep == math::Scalar{0} ? value : mean + (value - mean) / total;
102 ++count;
103 if (count >= min_observed) {
104 result[row] = mean;
105 }
106 }
107 return result;
108}
109
122inline math::Vector exponential_line(math::SeriesView closes, std::size_t span) {
123 const auto alpha = analytics::alpha_from_span(span);
124 std::size_t observations = 0;
125 for (math::Index row = 0; row < closes.size(); ++row) {
126 observations += math::observed(closes[row]) ? 1 : 0;
127 }
128 if (observations < 3 * span) {
129 return adjusted_ema(closes, alpha, span);
130 }
131 return analytics::ema(closes, alpha, span);
132}
133
145inline std::optional<math::SeriesView> trailing(math::SeriesView values, std::size_t count) {
146 const auto needed = static_cast<math::Index>(count) + 1;
147 if (values.size() < needed) {
148 return std::nullopt;
149 }
150 return values.tail(needed);
151}
152
153} // namespace vanilla
154} // namespace strategy
155} // namespace algotradelib
Scalar alpha_from_span(std::size_t span)
Converts an EMA span to its smoothing factor, 2 / (span + 1).
Definition rolling.hpp:415
math::Vector ema(math::SeriesView values, Scalar alpha, std::size_t min_observed=1)
Computes the exponentially weighted moving average of a series.
Definition rolling.hpp:484
double Scalar
The floating-point type the analytics and math layers compute in (double).
Definition scalar.hpp:18
bool observed(Scalar value)
Tests whether a value is an observation.
Definition scalar.hpp:36
Eigen::Index Index
The signed index type of rows and columns.
Definition eigen.hpp:65
Vector unobserved(std::size_t count)
Makes a vector filled with missing().
Definition eigen.hpp:73
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,...
std::optional< math::SeriesView > trailing(math::SeriesView values, std::size_t count)
Returns the last count + 1 rows of a series.
Definition signal.hpp:145
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
math::Vector adjusted_ema(math::SeriesView values, math::Scalar alpha, std::size_t min_observed=1)
Computes the bias-adjusted exponential moving average.
Definition signal.hpp:82
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.
The last two values of an indicator line, for testing a crossing.
Definition signal.hpp:21
math::Scalar previous_
The value on the previous bar.
Definition signal.hpp:23
math::Scalar current_
The value on the latest bar.
Definition signal.hpp:25
bool rose_above(const Crossing &other) const
Tests whether this line crossed above another on the latest bar.
Definition signal.hpp:32
bool fell_below(const Crossing &other) const
Tests whether this line crossed below another on the latest bar.
Definition signal.hpp:41