8#define ATL_BROKER_ADAPTER_PRESENT 1
10#include "./client.hpp"
12#include "../../core/broker_session.hpp"
13#include "../../core/broker_traits.hpp"
29 static constexpr std::string_view
name =
"kis";
32namespace traits_detail {
40 static constexpr bool has_depth =
true;
43 static constexpr bool has_price_limits =
true;
46 static constexpr bool has_trade_prints =
true;
49 static constexpr bool has_batch_prices =
false;
52 static constexpr bool has_buying_power =
true;
58 static constexpr bool has_buying_power_quantity =
false;
67 static constexpr bool has_commission_schedule =
false;
70 static constexpr bool has_reference_data =
true;
73 static constexpr bool has_batch_reference_data =
false;
76 static constexpr bool has_calendar =
true;
79 static constexpr bool has_calendar_range =
true;
82 static constexpr bool has_calendar_sessions =
false;
91 static std::optional<BrokerError> validate_calendar(
Country country, std::optional<Date> from) {
95 if (country != Country::KR) {
97 error.
message_ =
"KIS publishes the domestic trading calendar only";
102 error.
message_ =
"calendar request requires a valid Gregorian date";
114 static constexpr bool supports_interval(
BarInterval interval) {
123 static std::optional<BrokerError> validate_bars(
const BarQuery& query) {
157 static std::optional<BrokerError> validate_place(
const OrderRequest& order) {
171 placed.
ack_ = std::move(raw.
value().ack_);
172 placed.
ref_ = make_ref(raw.
value().order_);
194 for (
auto& open_order : raw.
value().orders_) {
196 working.
order_ = std::move(open_order.order_);
197 working.
ref_ = make_ref(open_order.order_ref_);
199 orders.
orders_.push_back(std::move(working));
227 "KIS requires an explicit quantity on a modification or cancellation, including a full "
228 "cancellation; read the amendable quantity from working orders first";
233 amendment.
order_ = from_ref(ref);
241 : (instruction.
resting_ ? instruction.
resting_->time_in_force_ : std::nullopt);
245 if (!condition || !session) {
251 "KIS re-sends the order code on an amendment and cannot compose one without the order's "
252 "validity condition and session; state them on the shape or build the instruction with "
253 "reprice() or replace_with(), which take them from the resting order";
277 return to_amendment(ref, instruction);
290 return to_amendment(ref, instruction);
311 error.
message_ =
"KIS order history requires an inclusive from and to calendar date";
317 "KIS order history is not filtered by instrument by this adapter; filter the returned "
323 error.
message_ =
"KIS order history pages internally and exposes no cursor";
328 error.
message_ =
"KIS order history returns every page and cannot honor a row limit";
338 static constexpr bool has_account_discovery =
false;
341 static constexpr bool has_client_order_id =
false;
344 static constexpr bool has_trigger_price =
true;
350 static constexpr bool has_working_orders =
true;
356 static constexpr bool has_amendable_quantity =
true;
362 static constexpr bool working_orders_state_terminal =
false;
365 static constexpr bool has_order_by_id =
false;
368 static constexpr bool has_partial_cancel =
true;
371 static constexpr bool history_requires_range =
true;
374 static constexpr bool has_history_cursor =
false;
380 static constexpr bool has_history_limit =
false;
383 static constexpr bool has_history_symbol_filter =
false;
395 return asked == Venue::UNSPECIFIED ? Venue::KRX : asked;
401: kis::traits_detail::Normalizers, kis::traits_detail::Capabilities {
458 template <
typename Token>
460 return client.
async_instrument(std::move(subject), std::forward<Token>(token));
472 template <
typename Token>
487 template <
typename Token>
501 template <
typename Token>
514 template <
typename Token>
527 template <
typename Token>
529 return client.
async_bars(std::move(query), std::forward<Token>(token));
540 template <
typename Token>
554 template <
typename Token>
567 template <
typename Token>
569 return client.
async_holdings(account, std::forward<Token>(token));
581 template <
typename Token>
583 return client.
async_place_order(account, std::move(order), std::forward<Token>(token));
595 template <
typename Token>
602 return client.
async_replace_order(account, std::move(amendment), std::forward<Token>(token));
614 template <
typename Token>
621 return client.
async_cancel_order(account, std::move(amendment), std::forward<Token>(token));
632 template <
typename Token>
646 template <
typename Token>
660: kis::traits_detail::Normalizers, kis::traits_detail::Capabilities {
771 return client.
bars(std::move(query));
817 return client.
place_order(account, std::move(order));
847 return client.
cancel_order(account, std::move(amendment));
A three-letter currency code, such as KRW or USD (ISO 4217 style).
Either a value or a BrokerError.
Result(T value)
Constructs a successful result.
BrokerError & error()
Returns the error.
T & value()
Returns the value.
A blocking KIS client: each call runs a KisClient request on a private event loop and returns its res...
Result< TradingCalendar > calendar(Date from, bool refresh=false)
Returns the trading calendar from a date on; see KisClient::async_calendar (cached).
Result< OrderPage > order_history(KisAccount account, KisHistoryRange range)
Returns the orders placed over a date range, with their fills.
Result< QuoteSnapshot > quote(InstrumentId instrument)
Returns a quote; see KisClient::async_quote.
Result< KisOrderAck > replace_order(KisAccount account, KisAmendment amendment)
Amends an order's price or quantity; the outcome can be unknown after an error (see KisClient::async_...
Result< BuyingPower > buying_power(Currency currency, KisAccount account)
Returns the account's buying power, in won.
Result< std::vector< TradePrint > > trades(InstrumentId instrument, int count)
Returns an instrument's recent trades.
Result< KisOpenOrderPage > open_orders(KisAccount account)
Returns the orders that can still be amended or cancelled; see KisClient::async_open_orders (includin...
Result< HoldingsSnapshot > holdings(KisAccount account)
Returns the account's holdings.
Result< Instrument > instrument(InstrumentId subject)
Returns an instrument's reference data.
Result< PriceLimits > price_limits(InstrumentId instrument)
Returns an instrument's price band for today.
const network::RateLimitStats * rate_limit_stats() const
Returns the rate limiter's statistics (safe to read between calls).
Result< DepthSnapshot > depth(InstrumentId instrument)
Returns the order book (ten levels a side).
Result< BarSeries > bars(BarQuery query)
Returns bars; see KisClient::async_bars.
Result< KisOrderAck > place_order(KisAccount account, OrderRequest order)
Places a cash order; see KisClient::async_place_order.
Result< KisOrderAck > cancel_order(KisAccount account, KisAmendment amendment)
Cancels an order; the outcome can be unknown after an error, and the order may still rest (see KisCli...
The asynchronous KIS REST client: market data, account inquiries and orders for domestic stocks.
auto async_place_order(KisAccount account, OrderRequest order, CompletionToken &&token)
Places a cash order.
auto async_quote(InstrumentId instrument, CompletionToken &&token)
Requests a quote.
auto async_calendar(Date from, bool refresh, CompletionToken &&token)
Requests the trading calendar from a date on, and caches it for the client's life.
auto async_cancel_order(KisAccount account, KisAmendment amendment, CompletionToken &&token)
Cancels an order (all or part of it, as amendment says).
auto async_trades(InstrumentId instrument, int count, CompletionToken &&token)
Requests an instrument's recent trades.
auto async_holdings(KisAccount account, CompletionToken &&token)
Requests the account's holdings.
auto async_order_history(KisAccount account, KisHistoryRange range, CompletionToken &&token)
Requests the orders placed over a date range, with their fills.
const network::RateLimitStats * rate_limit_stats() const
Returns the rate limiter's statistics.
auto async_open_orders(KisAccount account, CompletionToken &&token)
Requests every order that can still be amended or cancelled.
auto async_instrument(InstrumentId instrument, CompletionToken &&token)
Requests an instrument's reference data.
auto async_replace_order(KisAccount account, KisAmendment amendment, CompletionToken &&token)
Amends an order's price or quantity.
auto async_buying_power(Currency currency, KisAccount account, CompletionToken &&token)
Requests the account's buying power (the account-level amount, in won).
auto async_price_limits(InstrumentId instrument, CompletionToken &&token)
Requests an instrument's price band for today (from its current-price inquiry).
auto async_depth(InstrumentId instrument, CompletionToken &&token)
Requests the order book (ten levels a side).
auto async_bars(BarQuery query, CompletionToken &&token)
Requests bars, reading KIS pages until count_ bars are collected.
Placeholder types and the refusal used by DataOnlyTraits.
The Korea Investment & Securities (KIS) Open API client.
Date today_in_seoul()
Returns today's date in Korea (UTC+9), the date KIS requests are made in.
std::optional< BrokerError > unsupported_client_order_id(const OrderRequest &order)
Refuses an idempotency key, which KIS does not offer to individual customers.
constexpr bool publishes_bar_interval(BarInterval interval) noexcept
Tests whether KIS publishes a chart at an interval.
std::optional< BrokerError > unsupported_bar_interval(BarInterval interval)
Refuses a bar interval KIS publishes no chart for (publishes_bar_interval).
The library: broker-neutral types (core), and the modules below.
SellableSource
Where the library gets a broker's sellable quantity.
@ HOLDINGS
On the holdings snapshot, at no extra request.
@ INVALID_ARGUMENT
The request was invalid, refused by the client before sending or by the broker.
Country
A country (market) the library supports.
Venue
A trading venue: an exchange, or the combined view across exchanges.
BarInterval
The period one bar covers.
bool is_valid_date(const Date &date)
Tests whether a date exists in the Gregorian calendar, in years 1 to 9999.
constexpr Venue kis_effective_route(Venue asked) noexcept
Returns the venue a KIS order actually reaches.
std::optional< Decimal64 > amended_trigger_price(const AmendInstruction &instruction)
Returns the trigger price an amendment leaves the order with.
A modification or cancellation of a working order.
Venue venue_
The venue the order rests at, for a broker whose amendment needs it (KIS).
std::optional< OrderShape > resting_
The shape the order has now, or unset if unknown.
std::optional< Decimal64 > quantity_
The quantity affected; never substituted if a broker needs one and it is missing.
OrderShape shape_
The shape the order should have afterwards.
bool all_remaining_
Whether the whole remaining quantity is affected, rather than quantity_.
BarInterval interval_
The period of each bar; an interval the broker does not publish is refused.
The error a broker or transport operation returns.
std::string message_
A human-readable description, for logs; do not parse it.
ErrorCategory category_
The kind of failure; the field to branch on.
std::string broker_code_
The broker's own error code, verbatim (for example KIS's EGW00201).
bool reached_broker_
Whether a request was sent before this error.
kis::KisAccount Account
The account type.
static Result< DepthSnapshot > depth(Client &client, InstrumentId instrument)
Returns the order book.
static Result< BarSeries > bars(Client &client, BarQuery query)
Returns bars, paging inside the client.
kis::KisConfig Config
The configuration type.
kis::KisBlockingClient Client
The client type.
static const network::RateLimitStats * rate_limit_stats(const Client &client)
Returns this client's pacing statistics, or null when it is unpaced.
kis::KisHistoryRange HistoryQuery
The order-history query type.
static Result< TradingCalendar > calendar(Client &client, Country, std::optional< Date > from)
Returns the calendar, supplying today when no date was given.
static Result< OrderPage > order_history(Client &client, const Account &account, HistoryQuery query)
Returns order history for the bound account.
static Result< Instrument > instrument(Client &client, InstrumentId subject)
Returns static reference data for one instrument.
static Result< std::vector< TradePrint > > trades(Client &client, InstrumentId instrument, int count)
Returns recent executions.
kis::Broker BrokerTag
The broker tag.
static constexpr std::string_view name
The broker's name.
static Result< PriceLimits > price_limits(Client &client, InstrumentId instrument)
Returns today's price bounds.
static Result< BuyingPower > buying_power(Client &client, const Account &account, Currency currency)
Returns what the bound account may spend in currency.
static constexpr bool blocking
true: requests return their result directly.
static constexpr Venue effective_route(Venue asked) noexcept
Where an order carrying asked actually goes; see kis_effective_route.
kis::KisAmendment Amendment
The amendment type.
static Result< PlaceAck > cancel_order(Client &client, const Account &account, Amendment amendment)
Cancels an order for the bound account.
static Result< WorkingOrdersResult > working_orders(Client &client, const Account &account)
Returns the amendable orders for the bound account.
kis::KisOpenOrderPage WorkingOrdersResult
The working-order result type.
static Result< QuoteSnapshot > quote(Client &client, InstrumentId instrument)
Returns a quote.
static Result< PlaceAck > place_order(Client &client, const Account &account, OrderRequest order)
Submits an order for the bound account.
static Result< HoldingsSnapshot > holdings(Client &client, const Account &account)
Returns holdings for the bound account.
kis::KisOrderAck PlaceAck
The order acknowledgement type.
static Result< PlaceAck > replace_order(Client &client, const Account &account, Amendment amendment)
Modifies an order for the bound account.
kis::KisOrderAck PlaceAck
The order acknowledgement type.
static constexpr Venue effective_route(Venue asked) noexcept
Where an order carrying asked actually goes; see kis_effective_route.
static auto holdings(Client &client, const Account &account, Token &&token)
Forwards a holdings request for the bound account.
static auto replace_order(Client &client, const Account &account, Amendment amendment, Token &&token)
Forwards an order modification for the bound account.
static auto price_limits(Client &client, InstrumentId instrument, Token &&token)
Forwards a price-bound request.
static auto working_orders(Client &client, const Account &account, Token &&token)
Forwards an amendable-order inquiry for the bound account.
static auto bars(Client &client, BarQuery query, Token &&token)
Forwards a bar request.
kis::KisHistoryRange HistoryQuery
The order-history query type.
kis::KisConfig Config
The configuration type.
kis::KisOpenOrderPage WorkingOrdersResult
The working-order result type.
kis::KisClient Client
The client type.
static constexpr bool blocking
false: requests complete through a completion token.
static auto instrument(Client &client, InstrumentId subject, Token &&token)
Forwards a reference-data request for one instrument.
static auto quote(Client &client, InstrumentId instrument, Token &&token)
Forwards a quote request.
static auto trades(Client &client, InstrumentId instrument, int count, Token &&token)
Forwards a recent-execution request.
kis::Broker BrokerTag
The broker tag.
static const network::RateLimitStats * rate_limit_stats(const Client &client)
Returns this client's pacing statistics, or null when it is unpaced.
kis::KisAmendment Amendment
The amendment type.
kis::KisAccount Account
The account type.
static auto calendar(Client &client, Country, std::optional< Date > from, Token &&token)
Forwards a calendar request (the market argument is ignored; validate_calendar checks it).
static auto buying_power(Client &client, const Account &account, Currency currency, Token &&token)
Forwards a buying-power request for the bound account.
static auto order_history(Client &client, const Account &account, HistoryQuery query, Token &&token)
Forwards an order-history inquiry for the bound account.
static auto depth(Client &client, InstrumentId instrument, Token &&token)
Forwards an order book request.
static constexpr std::string_view name
The broker's name.
static auto place_order(Client &client, const Account &account, OrderRequest order, Token &&token)
Forwards an order submission for the bound account.
static auto cancel_order(Client &client, const Account &account, Amendment amendment, Token &&token)
Forwards an order cancellation for the bound account.
Describes one broker client to the library: its types, capabilities, call thunks and normalizers.
Identifies an instrument: its country, venue and symbol.
The filter for an order-history inquiry.
std::optional< std::string > symbol_
Only this symbol, where the broker supports the filter.
std::optional< int > limit_
The most rows to return, where the broker supports a limit.
std::optional< std::string > cursor_
A previous page's next_cursor_, passed back unchanged.
std::optional< Date > from_
The first date to include; required where BrokerCaps::history_requires_range.
std::optional< Date > to_
The last date to include.
A broker's reference to one order, used to amend or cancel it.
std::string primary_
The order number or id.
An order to place, in broker-neutral form.
std::optional< TimeInForce > time_in_force_
The time in force; unset means "keep the resting order's".
std::optional< Decimal64 > price_
The price, for a basis that takes one.
std::optional< OrderSession > session_
The session; unset means "keep the resting order's".
OrderType type_
The price basis.
An accepted order: the acknowledgement and the reference to address it with.
OrderRef< Broker > ref_
The reference to amend or cancel the order with.
OrderAck ack_
The acknowledgement.
An order still open to modification or cancellation.
OrderRef< Broker > ref_
The reference to amend or cancel the order with.
std::optional< Decimal64 > amendable_quantity_
How much the broker says may still be amended. Empty means it stated none, not zero.
OrderSnapshot order_
The order's state.
The orders open to modification or cancellation at one point in time.
std::vector< WorkingOrder< Broker > > orders_
The open orders.
std::chrono::system_clock::time_point received_at_
When the listing was received, on this machine's clock.
The KIS broker tag: order references are typed by it, so a KIS reference works with both KIS clients ...
static constexpr std::string_view name
The broker's name, "kis".
A KIS account: the account number and product code every account request names.
An amendment or cancellation of a KIS order.
bool all_remaining_
Whether the whole remaining quantity is affected (KIS's QTY_ALL_ORD_YN), rather than quantity_.
OrderType type_
The order type it should have.
KisOrderRef order_
The order to amend or cancel.
std::optional< Decimal64 > trigger_price_
The trigger price (KIS's CNDT_PRIC), for a STOP_LIMIT order.
OrderSession session_
The session it should be in.
Decimal64 quantity_
The quantity affected; KIS requires a positive whole number even with all_remaining_.
TimeInForce time_in_force_
The execution condition it should have.
std::optional< Decimal64 > price_
The price the order should have: required for an order type that takes one, on a cancellation too.
Venue venue_
The venue where the order rests (the codes differ by venue).
KIS credentials (app key and secret), demo or real account, and the market-data tape.
The date range of a KIS order-history inquiry, both ends included (Korean dates).
KIS's list of orders that can still be amended or cancelled.
KIS's acknowledgement of an accepted order, amendment or cancellation.
A KIS order's address: branch number and order number, both kept.
std::string order_number_
The order number within that branch (KIS's ODNO).
std::string branch_number_
The branch that recorded the order (KIS's KRX_FWDG_ORD_ORGNO).
A rate limiter's counters per traffic class, its current budget, and the broker's refusals (from Rate...