algotradelib 0.0.0.9000
C++ header-only library for algorithmic trading
Loading...
Searching...
No Matches
frame.hpp
1#pragma once
2
3#include "./conversion.hpp"
4#include "./time_index.hpp"
5
6#include "../math/matrix.hpp"
7
8#include <algotradelib/core>
9
10#include <array>
11#include <cstddef>
12#include <stdexcept>
13#include <string_view>
14#include <utility>
15#include <vector>
16
17namespace algotradelib {
18namespace analytics {
19
21enum class BarField {
22 OPEN,
23 HIGH,
24 LOW,
25 CLOSE,
26 VOLUME,
27 TRADED_VALUE,
28};
29
31inline constexpr std::array<BarField, 6> all_bar_fields{
32 BarField::OPEN,
33 BarField::HIGH,
34 BarField::LOW,
35 BarField::CLOSE,
36 BarField::VOLUME,
37 BarField::TRADED_VALUE,
38};
39
41inline constexpr std::size_t bar_field_count = all_bar_fields.size();
42
48inline constexpr std::size_t bar_field_index(BarField field) noexcept {
49 return static_cast<std::size_t>(field);
50}
51
57inline constexpr std::string_view bar_field_name(BarField field) noexcept {
58 switch (field) {
59 case BarField::OPEN:
60 return "open";
61 case BarField::HIGH:
62 return "high";
63 case BarField::LOW:
64 return "low";
65 case BarField::CLOSE:
66 return "close";
67 case BarField::VOLUME:
68 return "volume";
69 case BarField::TRADED_VALUE:
70 return "traded_value";
71 }
72 return "";
73}
74
75static_assert(
76 lists_every_value(all_bar_fields, [](BarField field) { return !bar_field_name(field).empty(); }),
77 "all_bar_fields must list every BarField"
78);
79
90public:
92 SeriesFrame() = default;
93
101 : instrument_(std::move(instrument)), index_(std::move(index)) {
102 values_ = math::Matrix::Constant(
103 static_cast<math::Index>(index_.size()),
104 static_cast<math::Index>(bar_field_count),
105 missing()
106 );
107 }
108
113 std::size_t rows() const noexcept { return index_.size(); }
114
119 std::size_t columns() const noexcept { return bar_field_count; }
120
125 const TimeIndex& time() const noexcept { return index_; }
126
131 const InstrumentId& instrument() const noexcept { return instrument_; }
132
139 return values_.col(static_cast<math::Index>(bar_field_index(field)));
140 }
141
146 math::SeriesView close() const { return column(BarField::CLOSE); }
147
152 math::SeriesView open() const { return column(BarField::OPEN); }
153
158 math::SeriesView high() const { return column(BarField::HIGH); }
159
164 math::SeriesView low() const { return column(BarField::LOW); }
165
170 math::SeriesView volume() const { return column(BarField::VOLUME); }
171
180 Scalar at(std::size_t row, BarField field) const {
181 if (row >= rows()) {
182 throw std::out_of_range("frame row is past the end");
183 }
184 return values_(
185 static_cast<math::Index>(row), static_cast<math::Index>(bar_field_index(field))
186 );
187 }
188
197 void set(std::size_t row, BarField field, Scalar value) {
198 if (row >= rows()) {
199 throw std::out_of_range("frame row is past the end");
200 }
201 values_(
202 static_cast<math::Index>(row), static_cast<math::Index>(bar_field_index(field))
203 ) = value;
204 }
205
210 math::MatrixView values() const { return values_; }
211
212private:
213 InstrumentId instrument_;
214 TimeIndex index_;
215 math::Matrix values_;
216};
217
228inline SeriesFrame from_bars(const BarSeries& series) {
229 std::vector<TimeIndex::Instant> stamps;
230 stamps.reserve(series.bars_.size());
231 for (const auto& bar : series.bars_) {
232 stamps.push_back(bar.timestamp_);
233 }
234
235 SeriesFrame frame(TimeIndex(std::move(stamps)), series.instrument_);
236 for (std::size_t row = 0; row < series.bars_.size(); ++row) {
237 const auto& bar = series.bars_[row];
238 // An absent open is a trading day on which nothing traded. It stays unobserved
239 // rather than becoming zero or the previous close.
240 if (bar.open_) {
241 frame.set(row, BarField::OPEN, to_scalar(*bar.open_));
242 }
243 frame.set(row, BarField::HIGH, to_scalar(bar.high_));
244 frame.set(row, BarField::LOW, to_scalar(bar.low_));
245 frame.set(row, BarField::CLOSE, to_scalar(bar.close_));
246 frame.set(row, BarField::VOLUME, to_scalar(bar.volume_));
247 if (bar.traded_value_) {
248 frame.set(row, BarField::TRADED_VALUE, to_scalar(*bar.traded_value_));
249 }
250 }
251 return frame;
252}
253
254} // namespace analytics
255} // namespace algotradelib
One instrument's bars as numeric columns: one row per bar, one column per BarField.
Definition frame.hpp:89
const TimeIndex & time() const noexcept
Returns the instants of the rows.
Definition frame.hpp:125
std::size_t columns() const noexcept
Returns the number of columns.
Definition frame.hpp:119
const InstrumentId & instrument() const noexcept
Returns the instrument the frame describes.
Definition frame.hpp:131
math::SeriesView close() const
Returns the close column.
Definition frame.hpp:146
math::SeriesView volume() const
Returns the volume column.
Definition frame.hpp:170
SeriesFrame()=default
Constructs an empty frame.
Scalar at(std::size_t row, BarField field) const
Reads one value.
Definition frame.hpp:180
void set(std::size_t row, BarField field, Scalar value)
Writes one value.
Definition frame.hpp:197
math::SeriesView open() const
Returns the open column.
Definition frame.hpp:152
std::size_t rows() const noexcept
Returns the number of rows.
Definition frame.hpp:113
math::SeriesView high() const
Returns the high column.
Definition frame.hpp:158
math::MatrixView values() const
Returns all values.
Definition frame.hpp:210
SeriesFrame(TimeIndex index, InstrumentId instrument={})
Constructs a frame with one row per instant, every value missing().
Definition frame.hpp:100
math::SeriesView low() const
Returns the low column.
Definition frame.hpp:164
math::SeriesView column(BarField field) const
Returns one field's column.
Definition frame.hpp:138
The instants a frame's rows correspond to, strictly ascending.
TimeIndex()=default
Constructs an empty index.
std::size_t size() const noexcept
Returns the number of instants.
Conversions between exact Decimal64 values and the analytics Scalar.
The linear algebra types of the math module: Matrix, Vector, SeriesView, MutableSeriesView,...
Returns, rolling statistics, indicators and performance metrics over numeric series.
constexpr std::array< BarField, 6 > all_bar_fields
Every BarField, in declaration order.
Definition frame.hpp:31
BarField
A bar field, used as a column of a SeriesFrame.
Definition frame.hpp:21
constexpr std::string_view bar_field_name(BarField field) noexcept
Returns a lowercase display name for a field, such as "close".
Definition frame.hpp:57
constexpr std::size_t bar_field_count
The number of BarField values, and so of columns in a SeriesFrame.
Definition frame.hpp:41
Scalar missing()
Returns the value that stands for "no observation"; see math::missing.
Definition scalar.hpp:28
constexpr std::size_t bar_field_index(BarField field) noexcept
Returns the column position of a field in a SeriesFrame.
Definition frame.hpp:48
Scalar to_scalar(const Decimal64 &value)
Converts an exact decimal to the nearest Scalar.
SeriesFrame from_bars(const BarSeries &series)
Converts a bar series into a frame of Scalar columns.
Definition frame.hpp:228
double Scalar
The floating-point type the analytics and math layers compute in (double).
Definition scalar.hpp:18
Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor > Matrix
A dense, column-major matrix of Scalar.
Definition eigen.hpp:45
Eigen::Index Index
The signed index type of rows and columns.
Definition eigen.hpp:65
Eigen::Ref< const Matrix > MatrixView
A read-only reference to a whole matrix.
Definition eigen.hpp:62
Eigen::Ref< const Vector > SeriesView
A read-only reference to one series.
Definition eigen.hpp:56
The library: broker-neutral types (core), and the modules below.
constexpr bool lists_every_value(const std::array< Enum, N > &values, IsEnumerator is_enumerator) noexcept
Tests whether a list holds every value of an enum exactly once, in any order.
The bars of one instrument and interval, oldest first.
InstrumentId instrument_
The instrument.
std::vector< Bar > bars_
The bars, oldest first.
Identifies an instrument: its country, venue and symbol.
Definition types.hpp:78