8constexpr double qty_epsilon = 1e-10;
9bool entry_like(
int type) {
return type == 0 || type == 1 || type == 3; }
10bool unpriced(
const admission::CommandObservation& o) {
return std::isnan(o.prices.limit) && std::isnan(o.prices.stop); }
11bool ordinary_terminal_call(
const admission::CommandObservation& o) {
12 return !std::isnan(o.requested_quantity) && unpriced(o)
13 && o.configuration.process_on_close && o.configuration.calc_on_fills
14 && !o.configuration.fill_recalculation && o.placement_side == 0;
16bool fixed_market_call(
const admission::CommandObservation& o) {
17 return std::isfinite(o.requested_quantity) && o.requested_quantity > qty_epsilon
18 && unpriced(o) && o.oca_name.empty() && (o.quantity_type < 0 || o.quantity_type == 0);
20bool all_in(
const admission::CommandObservation& o) {
21 if (!o.original_sizing)
return false;
22 const auto& c=o.configuration;
const auto& s=*o.original_sizing;
23 const double margin=o.buy?c.long_margin:c.short_margin;
24 return c.default_quantity_type==1 && std::abs(c.default_quantity_value-100.0)<1e-12
25 && std::isfinite(margin) && std::abs(margin/100.0-1.0)<1e-12
26 && std::isfinite(s.quantity) && std::isfinite(s.equity) && std::isfinite(s.price)
27 && std::isfinite(s.mark) && std::isfinite(s.fx) && s.fx>0.0;
29bool removed(
const admission::CommandEvent& e,uint64_t incarnation) {
30 return std::find(e.removed.begin(),e.removed.end(),incarnation)!=e.removed.end();
48 return o.
kind==admission::CommandKind::Entry && fixed_market_call(o)
56 const auto& o=d.
observation();
return o && o->kind==admission::CommandKind::Entry
57 && unpriced(*o) && o->placement_side==0 && !(o->prior_close_quantity>qty_epsilon) && all_in(*o);
60 const auto& o=d.
observation();
return o && o->kind==admission::CommandKind::Entry
61 && unpriced(*o) && !std::isnan(o->requested_quantity) && !std::isnan(o->signal_close)
62 && o->placement_side==0 && !(o->prior_close_quantity>qty_epsilon)
63 && std::isfinite(o->buy?o->configuration.long_margin:o->configuration.short_margin)
64 && (o->buy?o->configuration.long_margin:o->configuration.short_margin)>0.0
65 && std::isfinite(o->explicit_equity) && std::isfinite(o->explicit_price);
71 const auto& s=*o.original_sizing;
return s.quantity>qty_epsilon && s.equity>0 && s.mark>0;
75 if (!event)
throw std::logic_error(
"null admission history event");
82 for(
const auto& held:events) {
84 if(
const auto* command=std::get_if<CommandEvent>(&event)) {
85 const auto& e=*command;
const auto& o=*e.observation;
const auto seq=o.command;
86 if(e.outcome==Outcome::IgnoredTradingWindow || e.outcome==Outcome::IgnoredIntradayLoss
87 || e.outcome==Outcome::RejectedIntradayCap)
continue;
88 if(o.kind==CommandKind::Entry) {
90 int count=0;
bool noncandidate=
false;
91 for(
const auto& old:e.before)
if(old.bar==o.bar && entry_like(old.type)) {
96 for(
const auto& old:e.before)
if(removed(e,old.incarnation)) {
97 const bool is_entry=entry_like(old.type);
100 if(is_entry&&old.placement_side==0)h.
pair_causes[old.bar]=seq;
103 if((e.outcome==Outcome::RejectedAffordability||e.outcome==Outcome::OpeningRejectedReductionAdmitted)
104 && ordinary_terminal_call(o))h.
pair_causes[o.bar]=seq;
105 }
else if(o.kind==CommandKind::Raw) {
107 for(
const auto& old:e.before)
if(removed(e,old.incarnation)&&entry_like(old.type)) {
109 if(old.placement_side==0)h.
pair_causes[old.bar]=seq;
110 if(o.configuration.process_on_close&&o.configuration.calc_on_fills&&!o.configuration.fill_recalculation)h.
pair_causes[o.bar]=seq;
113 for(
const auto& old:e.before) {
115 if(removed(e,old.incarnation)&&entry_like(old.type)) {
116 if(old.placement_side==0)h.
pair_causes[old.bar]=seq;
117 if(o.configuration.process_on_close&&o.configuration.calc_on_fills&&!o.configuration.fill_recalculation)h.
pair_causes[o.bar]=seq;
121 }
else if(
const auto* review=std::get_if<ReviewEvent>(&event)) {
122 if (!apply_reviews)
continue;
123 const auto cp=review->receipt.checkpoint;
124 if(cp!=Checkpoint::TerminalGross)
for(
const auto& order:review->reviewed) {
127 if(cp!=Checkpoint::DefaultGross || review->reviewed.empty()) {
129 for(
auto it=causes.begin();it!=causes.end();) {
130 if(it->first<review->receipt.bar)it=causes.erase(it);
else ++it;
138 for(
auto it=journal.
events().rbegin();it!=journal.
events().rend();++it)
139 if(
const auto* e=std::get_if<admission::CommandEvent>(&*it)) {
141 case admission::Outcome::RejectedIntradayCap:
case admission::Outcome::RejectedFrozenMarketCap:
142 case admission::Outcome::RejectedAffordability:
case admission::Outcome::RejectedPricedCap:
143 case admission::Outcome::OpeningRejectedReductionAdmitted:
return e->observation->bar;
const std::shared_ptr< const CommandObservation > & observation() const
const std::optional< ReviewReceipt > & review() const
const std::vector< Event > & events() const
std::variant< CommandEvent, ReviewEvent, SizingEvent > Event
bool explicit_qualification(const admission::Draft &draft)
const admission::Event & event_ref(const admission::Event &event)
int last_rejected_command_bar(const admission::Journal &journal)
bool awaits_pair_review(const admission::Draft &draft)
bool original_default_call(const admission::CommandObservation &o)
bool default_gross_scope(const admission::Configuration &c)
bool opening_qualification(const admission::Draft &draft)
History admission_history(const admission::Journal &journal)
bool awaits_default_review(const admission::Draft &draft)
bool original_pair_call(const admission::CommandObservation &o)
static History fold_admission_history(const Range &events, bool apply_reviews=true)
bool explicit_pair_scope(const admission::Configuration &c)
double requested_quantity
double quantized_fixed_quantity
Configuration configuration
double intraday_loss_limit
double default_quantity_value
int default_quantity_type
std::map< int, uint64_t > pair_causes
std::map< int, uint64_t > default_causes