FastMM documentation
FastMM C++ API 0.6.0
Public headers, tier 1 and tier 2
Loading...
Searching...
No Matches
signal_eval.hpp File Reference

evaluate_signal(): what a candidate predictor is worth, per horizon, before anyone writes a strategy around it. More...

#include "fastmm/research/feature_table.hpp"
#include <cstdint>
#include <span>
#include <string>
#include <string_view>
#include <vector>

Go to the source code of this file.

Classes

struct  fastmm::research::SignalBucket
 
struct  fastmm::research::HorizonEval
 
struct  fastmm::research::SignalEval
 
struct  fastmm::research::EvalConfig
 

Namespaces

namespace  fastmm
 
namespace  fastmm::research
 

Enumerations

enum class  fastmm::research::Feature : std::uint8_t { fastmm::research::Imbalance = 0 , fastmm::research::MicropriceEdge = 1 , fastmm::research::Spread = 2 }
 A built-in column, so the common signals need no array from the caller. More...
 

Functions

std::string_view fastmm::research::to_string (Feature f) noexcept
 
std::vector< double > fastmm::research::feature_values (const FeatureTable &t, Feature f)
 The feature of every row, in row order, in the units above.
 
SignalEval fastmm::research::evaluate_signal (const FeatureTable &t, std::span< const double > values, std::string_view name, const EvalConfig &cfg={})
 values must hold one signal value per row of t, in row order.
 
SignalEval fastmm::research::evaluate_feature (const FeatureTable &t, Feature f, const EvalConfig &cfg={})
 evaluate_signal() over feature_values(t, f).
 

Detailed Description

evaluate_signal(): what a candidate predictor is worth, per horizon, before anyone writes a strategy around it.

Three things come out of one pass over a FeatureTable:

  • the information coefficient, Spearman rank correlation between the signal and the forward mid move, and the same coefficient over equal-sized contiguous blocks of the sample, which is what says whether one hour carried it;
  • a decile table of the forward mid move by signal value, in basis points of the mid;
  • the conditional touch markout: for each bucket, what a quote resting at the touch would have made or lost by the horizon, one number per side, in basis points of the mid.

The touch markout is the one that decides whether a passive quote is viable. For a row with mid m, best bid b, best ask a and forward mid f:

buy_bps = (f - b) / m * 1e4 a resting bid that filled at b, marked at f sell_bps = (a - f) / m * 1e4 a resting ask that filled at a, marked at f

which split into (m - b) / m, the half spread the quote earned, plus or minus (f - m) / m, the move the mid made afterwards. Both sides of one quote average to the half spread, because the move cancels; the point of conditioning on a signal is that in a given bucket only one of them is the side that fills. The numbers are gross: subtract the venue's maker fee to compare.

Rows without a forward mid at a horizon are left out of every statistic of that horizon, and counted; they are never marked at a substitute price.