19#include <algotradelib/runner>
20#include <algotradelib/vanilla>
34using Clock = std::chrono::system_clock;
36InstrumentId samsung() {
return InstrumentId{Country::KR, Venue::COMBINED,
"005930"}; }
39Instrument samsung_reference() {
41 reference.
id_ = samsung();
42 reference.
type_ = SecurityType::STOCK;
54 void on_bar(Ctx& ctx,
const strategy::BarEvent&) {
56 ctx.log().note(
"saw bar " + std::to_string(bars_));
86 explicit ScriptedSource(
int bars) : remaining_(
bars) {}
98 live_runner.set_price_limits(samsung(), band);
104 if (remaining_ <= 0) {
111 bar.timestamp_ = Clock::time_point{} + std::chrono::hours(24 * (200 + fed_));
118 live_runner.context().set_last_price(samsung(),
bar.close_);
132 int reads() const noexcept {
return reads_; }
141void describe(
const runner::LoopReport& report) {
142 std::cout <<
"iterations : " << report.
iterations_ <<
'\n'
145 <<
"blocked : " << report.
blocked_ <<
" iteration(s)\n"
150 std::string_view(
"nothing"))
155 std::string_view(
"none"))
162 <<
" (" << report.phase_transitions_ <<
" transition(s))\n"
167 <<
"sent off-phase : " << report.sends_outside_permitted_phase_ <<
'\n'
174 <<
"bands withheld : " << report.price_bands_withheld_ <<
'\n'
175 <<
"refused unclamped: " << report.unclamped_orders_rejected_ <<
'\n';
176 for (
const auto& note : report.
notes_) {
177 std::cout <<
"note : " << note <<
'\n';
187Clock::time_point start_time() {
188 return Clock::time_point{} + std::chrono::hours(24 * 200);
198 std::cout <<
"a live loop with no broker attached\n\n";
200 LoopRunner live_runner;
201 live_runner.context().set_instrument(samsung_reference());
212 calendar.
country_ = algotradelib::Country::KR;
216 live_runner.context().set_calendar(calendar);
218 ScriptedSource source(4);
221 schedule.
bars_ = std::chrono::minutes(1);
222 schedule.
tick_ = std::chrono::minutes(1);
243 loop.allow_absent_portfolio();
249 loop.set_maximum_price_limits_age(std::chrono::minutes(20));
252 const auto report = loop.run(stop, 6);
256 std::cout <<
"\nthe strategy saw " << live_runner.strategy().bars_ <<
" bar(s)\n";
262 std::cout <<
"the order list was read " << source.reads() <<
" time(s) before the gate opened\n";
264 std::cout <<
"\nhow a real operator would stop this:\n"
265 <<
" runner::SignalStop::install(stop); // SIGINT and SIGTERM quiesce; SIGHUP ignored\n"
266 <<
" loop.set_control_file(runner::FileStopChannel(\"/var/run/atl/stop\"));\n"
267 <<
" echo withdraw > /var/run/atl/stop // or quiesce, or flatten\n\n"
268 <<
"and the trap worth knowing: a supervisor's grace period must exceed one loop\n"
269 <<
"iteration plus one request timeout, or its SIGKILL turns the cleanest stop into\n"
270 <<
"the worst one -- a process killed mid-request, with an order whose fate is unknown.\n";
static Decimal64 parse(std::string_view input)
Parses a decimal string exactly (no binary floating point).
A clock for tests: wait_for advances it instead of sleeping.
Runs a runner for a live session: polls a source on a schedule, gates placements, derives the market ...
void allow_unbounded_portfolio_age()
Accepts holdings of any age, instead of stating a maximum.
A stop request the loop polls; safe to set from a signal handler.
Runs a strategy: the runner, the polling loop, the order journal, and stopping.
Runner< Strategy, CapsType, DryTag, RecordingExecutor< DryTag > > DryRunner
A runner that sends nothing: handlers fire and instructions are recorded by a RecordingExecutor.
PollKind
What a PollingLoop polls for; each has a cadence in PollSchedule.
@ PRICE_LIMITS
Today's price bands, which an aggressive limit price is clamped to; polled second,...
PollOutcome
What became of one poll.
@ UNCHANGED
The poll succeeded and there was nothing new.
@ FAILED
The poll failed; counted toward the failure budget.
@ UPDATED
New data arrived and was fed to the runner, or installed in it (a calendar, price bands).
constexpr std::string_view stop_intent_name(StopIntent intent) noexcept
Returns a lowercase name for an intent, as written in the control file ("withdraw").
void bar(S &strategy, Ctx &context, const BarEvent &event)
Calls strategy.on_bar(context, event) if the strategy declares on_bar; otherwise does nothing.
void bars(S &strategy, Ctx &context, const BarSlice &slice)
Calls strategy.on_bars(context, slice) if the strategy declares on_bars; otherwise does nothing.
What a strategy sees and emits: events, intents, the portfolio, reconciliation and risk limits.
BarEvent make_bar_event(InstrumentId instrument, BarInterval interval, BarStamp stamp, Bar bar)
Makes a bar event, computing its period_end_ with bar_period_end.
constexpr std::string_view market_phase_name(MarketPhase phase) noexcept
Returns a lowercase name for a phase, such as "pre_open", for logs and display.
constexpr std::string_view halt_reason_name(HaltReason reason) noexcept
Returns a lowercase name for a hold, such as "portfolio_stale", for logs.
The library: broker-neutral types (core), and the modules below.
Currency currency_
The currency it trades in.
InstrumentId id_
The instrument.
PriceRule price_rule_
The price grid; kind UNKNOWN where the library has no table.
std::optional< Decimal64 > lot_size_
The order quantity increment, if the broker publishes one.
SecurityType type_
The kind of security, which selects the price grid.
std::optional< Decimal64 > lower_
The lowest price allowed today; empty means the same as for upper_.
std::optional< Decimal64 > upper_
The highest price allowed today.
Currency currency_
The currency of the bounds.
static PriceRule krx_equity()
Returns the KRX cash-equity tick table (January 2023 revision).
The trading days a broker reported for one market, ascending by date.
std::chrono::system_clock::time_point received_at_
When the calendar was received, on this machine's clock.
std::vector< TradingDay > days_
The days the broker reported, ascending. A date outside them is uncovered, not closed.
Country country_
The market this calendar is for.
One calendar date and whether the market opens on it.
std::size_t iterations_
How many iterations ran.
std::size_t blocked_
How many iterations were blocked from placing (a named cancellation may still have gone).
std::size_t failed(PollKind kind) const noexcept
Returns how many polls of a kind failed.
std::optional< strategy::HaltReason > final_gate_
The most fundamental hold in force when the run ended, whoever took it.
bool order_list_read_
Whether the broker's order list was read at least once.
std::optional< StopIntent > stopped_by_
The stop intent that ended the run, if one did.
std::size_t attempted(PollKind kind) const noexcept
Returns how many polls of a kind were attempted.
std::vector< std::string > notes_
Notes for the operator, such as an unrecognized control-file word or a missing policy.
How often a PollingLoop polls each kind; an unset interval disables that poll.
std::optional< std::chrono::nanoseconds > calendar_
How often to read the trading calendar; six hours by default.
std::chrono::nanoseconds tick_
The loop's step, which bounds how quickly a stop is noticed; not a poll.
std::optional< std::chrono::nanoseconds > price_limits_
How often to read today's price bands.
std::optional< std::chrono::nanoseconds > bars_
How often to fetch bars.
Date local_date(std::chrono::system_clock::time_point now) const
Returns the market's local date at an instant.
static SessionWindow krx()
Returns the KRX regular session, 09:00-15:30 KST.