8#define ATL_BROKER_ADAPTER_PRESENT 1
10#include "./client.hpp"
12#include "../../core/broker_session.hpp"
13#include "../../core/broker_traits.hpp"
15#include <boost/asio/associated_executor.hpp>
16#include <boost/asio/dispatch.hpp>
17#include <boost/asio/execution/outstanding_work.hpp>
18#include <boost/asio/post.hpp>
19#include <boost/asio/prefer.hpp>
35 static constexpr std::string_view
name =
"kiwoom";
38namespace traits_detail {
46 static constexpr bool has_depth =
true;
49 static constexpr bool has_price_limits =
true;
52 static constexpr bool has_trade_prints =
true;
58 static constexpr bool has_batch_prices =
false;
61 static constexpr bool has_buying_power =
true;
67 static constexpr bool has_buying_power_quantity =
true;
79 static constexpr bool has_commission_schedule =
false;
82 static constexpr bool has_reference_data =
true;
85 static constexpr bool has_batch_reference_data =
false;
91 static constexpr bool has_calendar =
false;
94 static constexpr bool has_calendar_range =
false;
97 static constexpr bool has_calendar_sessions =
false;
105 static std::optional<BrokerError> validate_calendar(
Country country, std::optional<Date> from) {
106 static_cast<void>(country);
107 static_cast<void>(from);
112 error.
message_ =
"Kiwoom publishes no trading calendar";
122 static constexpr bool supports_interval(
BarInterval interval) {
131 static std::optional<BrokerError> validate_bars(
const BarQuery& query) {
152 "Kiwoom's balance inquiry names one venue (kt00018 dmst_stex_tp: KRX or NXT) and publishes no "
153 "all-venue value, and whether that filters the positions or only values them is not stated. "
154 "This library will not present one venue's answer as the account's holdings unless you say "
155 "that is what it is: set KiwoomConfig::holdings_position_scope_ to "
156 "KiwoomPositionScope::VALUATION_ONLY to assert it, and "
157 "KiwoomConfig::holdings_sellable_scope_ separately for trde_able_qty. Until then read the rows "
158 "through session.client().holdings(). Both assertions are unverified; see KiwoomConfig's "
172 ref.secondary_ = order.
symbol_;
184 order.
symbol_ = ref.secondary_;
194 static std::optional<BrokerError> validate_place(
const OrderRequest& order) {
215 placed.
ack_ = std::move(raw.
value().ack_);
216 placed.
ref_ = make_ref(raw.
value().order_);
238 for (
auto& open_order : raw.
value().orders_) {
240 working.
order_ = std::move(open_order.order_);
241 working.
ref_ = make_ref(open_order.order_ref_);
243 orders.
orders_.push_back(std::move(working));
275 "a Kiwoom modification or cancellation affects a stated quantity; set all_remaining_ to "
276 "act on everything still resting, or build the instruction with cancel_all()";
279 if (
auto refusal = refuse_shape_change(instruction, cancel)) {
284 amendment.
order_ = from_ref(ref);
318 static std::optional<BrokerError> refuse_shape_change(
327 const auto refuse = [&error, cancel](
const char* what) {
329 std::string(
"Kiwoom's cancellation carries a quantity and nothing else, so it cannot "
330 "change an order's ") + what +
" on the way out" :
331 std::string(
"Kiwoom's amendment endpoints carry a quantity and a price only, so they "
332 "cannot change an order's ") + what +
333 "; cancel the order and place a new one instead";
341 const auto differs = [](
auto stated,
auto current) {
342 return stated.has_value() && (!current.has_value() || *stated != *current);
355 const bool restates_price = instruction.
resting_ &&
360 "Kiwoom's cancellation carries a quantity and no price, so it cannot reprice an order on "
361 "the way out; cancel it and place a new one instead";
366 const bool restates_trigger = instruction.
resting_ &&
371 "Kiwoom's cancellation carries a quantity and no trigger price, so it cannot move an "
372 "order's stop on the way out; cancel it and place a new one instead";
384 "Kiwoom's modification cannot change an order's price basis, validity condition or session, "
385 "and without the order's current shape this adapter cannot tell a restatement from a "
386 "change; build the instruction with reprice() or replace_with(), which take it from the "
391 const auto resting_condition = instruction.
resting_ ?
392 instruction.
resting_->time_in_force_ :
393 std::optional<TimeInForce>();
394 const auto resting_session = instruction.
resting_ ?
396 std::optional<OrderSession>();
398 return refuse(
"validity condition");
401 return refuse(
"session");
407 return refuse(
"price basis");
415 return refuse(
"price basis");
430 return to_amendment(ref, instruction,
false);
443 return to_amendment(ref, instruction,
true);
465 error.
message_ =
"Kiwoom's order-history inquiry lists one calendar date, which must be given";
468 if (query.
to_ && !(query.
to_->year_ == query.
from_->year_ &&
469 query.
to_->month_ == query.
from_->month_ &&
470 query.
to_->day_ == query.
from_->day_)) {
473 "Kiwoom's order-history inquiry lists one calendar date; ask for each date separately "
474 "rather than for a range";
479 error.
message_ =
"Kiwoom order history pages internally and exposes no cursor";
484 error.
message_ =
"Kiwoom order history documents no row limit and cannot honor one";
519 static constexpr bool has_account_discovery =
true;
522 static constexpr bool has_client_order_id =
false;
528 static constexpr bool has_trigger_price =
true;
534 static constexpr bool has_working_orders =
true;
537 static constexpr bool has_amendable_quantity =
true;
543 static constexpr bool working_orders_state_terminal =
false;
546 static constexpr bool has_order_by_id =
false;
549 static constexpr bool has_partial_cancel =
true;
552 static constexpr bool history_requires_range =
false;
555 static constexpr bool has_history_cursor =
false;
558 static constexpr bool has_history_limit =
false;
561 static constexpr bool has_history_symbol_filter =
true;
578: kiwoom::traits_detail::Normalizers, kiwoom::traits_detail::Capabilities {
636 template <
typename Token>
649 template <
typename Token>
663 template <
typename Token>
676 template <
typename Token>
689 template <
typename Token>
691 return client.
async_bars(std::move(query), std::forward<Token>(token));
702 template <
typename Token>
704 return client.
async_instrument(std::move(subject), std::forward<Token>(token));
714 template <
typename Token>
728 template <
typename Token>
750 template <
typename Token>
753 static_cast<void>(account);
755 [strand = client.
get_executor()](
auto&& handler)
mutable {
756 auto work = net::prefer(
757 net::get_associated_executor(handler), net::execution::outstanding_work.tracked
761 [handler = std::forward<
decltype(handler)>(handler), work = std::move(work)]()
mutable {
762 net::dispatch(work, [handler = std::move(handler)]()
mutable {
763 std::move(handler)(refuse_holdings());
771 return client.
async_holdings(account, std::forward<Token>(token));
783 template <
typename Token>
790 return client.
async_place_order(account, std::move(order), std::forward<Token>(token));
802 template <
typename Token>
809 return client.
async_replace_order(account, std::move(amendment), std::forward<Token>(token));
821 template <
typename Token>
828 return client.
async_cancel_order(account, std::move(amendment), std::forward<Token>(token));
839 template <
typename Token>
853 template <
typename Token>
867: kiwoom::traits_detail::Normalizers, kiwoom::traits_detail::Capabilities {
969 return client.
bars(std::move(query));
999 static_cast<void>(account);
1000 return refuse_holdings();
1028 return client.
place_order(account, std::move(order));
1058 return client.
cancel_order(account, std::move(amendment));
A three-letter currency code, such as KRW or USD (ISO 4217 style).
Decimal64()=default
Constructs zero.
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 Kiwoom client: each call runs a KiwoomClient request on a private event loop and returns i...
Result< PriceLimits > price_limits(InstrumentId instrument)
Returns today's upper and lower price bound.
Result< std::vector< TradePrint > > trades(InstrumentId instrument, int count)
Returns recent executions, newest first.
const KiwoomConfig & config() const noexcept
Returns the configuration; see KiwoomClient::config.
const network::RateLimitStats * rate_limit_stats() const
Returns the rate limiter's statistics.
Result< BuyingPower > buying_power(Currency currency, KiwoomAccount account)
Returns what the bound credential's account may spend.
Result< KiwoomOrderAck > replace_order(KiwoomAccount account, KiwoomAmendment amendment)
Modifies an existing order. The outcome can be unknown after an error; see KiwoomClient::async_replac...
Result< OrderPage > order_history(KiwoomAccount account, KiwoomHistoryQuery query)
Returns one day of order history.
Result< DepthSnapshot > depth(InstrumentId instrument)
Returns the resting orders on both sides of the book.
Result< KiwoomOrderAck > cancel_order(KiwoomAccount account, KiwoomAmendment amendment)
Cancels an existing order. The outcome can be unknown after an error; see KiwoomClient::async_cancel_...
Result< BarSeries > bars(BarQuery query)
Returns bars; see KiwoomClient::async_bars.
Result< QuoteSnapshot > quote(InstrumentId instrument)
Returns the current normalized quote or a structured error.
Result< std::vector< KiwoomAccountInfo > > accounts()
Returns the one account the bound credential drives.
Result< KiwoomOpenOrderPage > open_orders(KiwoomAccount account)
Returns every order still open to amendment.
Result< KiwoomOrderAck > place_order(KiwoomAccount account, OrderRequest order)
Submits a new order. The outcome can be unknown after an error; see KiwoomClient::async_place_order.
Result< Instrument > instrument(InstrumentId subject)
Returns static reference data for one instrument.
Result< HoldingsSnapshot > holdings(KiwoomAccount account)
Returns the holdings for KiwoomConfig::holdings_venue_; see KiwoomClient::async_holdings.
The asynchronous Kiwoom REST client: market data, account inquiries and orders for domestic stocks.
auto async_instrument(InstrumentId instrument, CompletionToken &&token)
Requests static reference data for one instrument, from ka10100 종목정보 조회.
auto async_buying_power(Currency currency, KiwoomAccount account, CompletionToken &&token)
Requests what the account may spend, from kt00001 예수금상세현황요청.
auto async_depth(InstrumentId instrument, CompletionToken &&token)
Requests the resting orders on both sides of the book, from ka10004 주식호가요청.
auto async_open_orders(KiwoomAccount account, CompletionToken &&token)
Requests every order still open to amendment, paging ka10075 미체결요청.
auto async_order_history(KiwoomAccount account, KiwoomHistoryQuery query, CompletionToken &&token)
Requests one day of order history, paging kt00007 계좌별주문체결내역상세요청.
auto async_cancel_order(KiwoomAccount account, KiwoomAmendment amendment, CompletionToken &&token)
Cancels an order, all or part of it (kt10003).
auto async_replace_order(KiwoomAccount account, KiwoomAmendment amendment, CompletionToken &&token)
Amends an order's quantity, price or trigger price (kt10002).
const KiwoomConfig & config() const noexcept
Returns the configuration (the session reads its holdings assertions from it).
auto async_bars(BarQuery query, CompletionToken &&token)
Requests bars, following Kiwoom's continuation pages from before_'s Korean date (or today).
auto async_place_order(KiwoomAccount account, OrderRequest order, CompletionToken &&token)
Places an order (kt10000 buy, kt10001 sell).
net::strand< net::any_io_executor > get_executor() const noexcept
Returns the client's strand.
auto async_price_limits(InstrumentId instrument, CompletionToken &&token)
Requests today's upper and lower price bound, from the same ka10007 response.
auto async_accounts(CompletionToken &&token)
Requests the one account the bound credential drives, from ka00001 계좌번호조회.
auto async_holdings(KiwoomAccount account, CompletionToken &&token)
Requests the holdings kt00018 lists for KiwoomConfig::holdings_venue_ (refused before sending until i...
const network::RateLimitStats * rate_limit_stats() const
Returns the rate limiter's statistics.
auto async_trades(InstrumentId instrument, int count, CompletionToken &&token)
Requests recent executions, newest first, from ka10003 체결정보요청.
auto async_quote(InstrumentId instrument, CompletionToken &&token)
Requests and normalizes a current quote, from ka10007 시세표성정보요청.
Placeholder types and the refusal used by DataOnlyTraits.
The Kiwoom Securities REST API client.
std::optional< BrokerError > unsupported_bar_interval(BarInterval interval)
Refuses a bar interval this client requests no chart for (chart_api_id).
constexpr const char * chart_rows_field(BarInterval interval) noexcept
Returns the array field a bar interval's chart endpoint returns its rows in.
std::optional< BrokerError > invalid_trigger(OrderType type, const std::optional< Decimal64 > &trigger)
Checks that a trigger price is present exactly when the order type takes one (only STOP_LIMIT,...
std::optional< BrokerError > unsupported_client_order_id(const OrderRequest &order)
Refuses an idempotency key, which Kiwoom does not offer (an order carrying client_order_id_ is refuse...
constexpr bool kiwoom_position_scope_asserted(KiwoomPositionScope scope) noexcept
Tests whether a holdings scope states what Kiwoom's holdings figure covers, so holdings may be read a...
constexpr const char * chart_api_id(BarInterval interval) noexcept
Returns the api-id of the chart endpoint for a bar interval.
constexpr Venue kiwoom_effective_route(Venue asked) noexcept
Returns the venue a Kiwoom order reaches: the one it names (Kiwoom requires one, so an order naming n...
The library: broker-neutral types (core), and the modules below.
SellableSource
Where the library gets a broker's sellable quantity.
@ NONE
No per-instrument inquiry: any figure comes on the holdings rows (Kiwoom), or there is none.
@ INVALID_ARGUMENT
The request was invalid, refused by the client before sending or by the broker.
Country
A country (market) the library supports.
constexpr Venue kiwoom_route(Venue asked) noexcept
Returns the venue a Kiwoom order reaches: the one it names. Kiwoom has no default venue,...
Venue
A trading venue: an exchange, or the combined view across exchanges.
BarInterval
The period one bar covers.
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.
static Result< Instrument > instrument(Client &client, InstrumentId subject)
Returns static reference data for one instrument.
kiwoom::KiwoomAccount Account
Kiwoom account selector, which carries nothing because Kiwoom takes nothing.
static Result< OrderPage > order_history(Client &client, const Account &account, HistoryQuery query)
Returns order history for the bound account.
static Result< HoldingsSnapshot > holdings(Client &client, const Account &account)
Serves the normalized holdings verb once a scope is asserted; see the asynchronous thunk.
kiwoom::KiwoomBlockingClient Client
The client type.
static constexpr bool blocking
true: requests return their result directly.
static constexpr std::string_view name
The broker's name.
kiwoom::Broker BrokerTag
The broker tag.
static Result< BuyingPower > buying_power(Client &client, const Account &account, Currency currency)
Returns what the bound account may spend in currency.
kiwoom::KiwoomOpenOrderPage WorkingOrdersResult
Kiwoom amendable-order result.
static Result< QuoteSnapshot > quote(Client &client, InstrumentId instrument)
Returns a quote.
kiwoom::KiwoomAccountInfo AccountListItem
Item type of the broker's own account listing.
kiwoom::KiwoomHistoryQuery HistoryQuery
Kiwoom order-history selector.
static Result< BarSeries > bars(Client &client, BarQuery query)
Returns bars, paging inside the client.
static Result< DepthSnapshot > depth(Client &client, InstrumentId instrument)
Returns the order book.
kiwoom::KiwoomOrderAck PlaceAck
Acknowledgement Kiwoom returns for an order instruction.
static Result< PlaceAck > place_order(Client &client, const Account &account, OrderRequest order)
Submits an order for the bound account.
static Result< std::vector< TradePrint > > trades(Client &client, InstrumentId instrument, int count)
Returns recent executions.
kiwoom::KiwoomConfig Config
Kiwoom application credentials and environment selection.
static const network::RateLimitStats * rate_limit_stats(const Client &client)
Returns the rate limiter's statistics.
static Result< PlaceAck > replace_order(Client &client, const Account &account, Amendment amendment)
Modifies an order for the bound account.
static Result< WorkingOrdersResult > working_orders(Client &client, const Account &account)
Returns the amendable orders for the bound account.
kiwoom::KiwoomAmendment Amendment
Kiwoom modification and cancellation instruction.
static Result< PlaceAck > cancel_order(Client &client, const Account &account, Amendment amendment)
Cancels an order for the bound account.
static Result< std::vector< AccountListItem > > accounts(Client &client)
Returns the one account the bound credential drives.
static constexpr Venue effective_route(Venue asked) noexcept
Returns the venue an order reaches; see kiwoom_route.
static Result< PriceLimits > price_limits(Client &client, InstrumentId instrument)
Returns today's price bounds.
static auto buying_power(Client &client, const Account &account, Currency currency, Token &&token)
Forwards a buying-power request for the bound account.
static constexpr std::string_view name
The broker's name.
static auto bars(Client &client, BarQuery query, Token &&token)
Forwards a bar request.
static auto quote(Client &client, InstrumentId instrument, Token &&token)
Forwards a quote request.
static auto holdings(Client &client, const Account &account, Token &&token)
Forwards a holdings request, or completes it with refuse_holdings() (sending nothing) while KiwoomCon...
static constexpr bool blocking
false: requests complete through a completion token.
static auto price_limits(Client &client, InstrumentId instrument, Token &&token)
Forwards a price-bound request.
static auto trades(Client &client, InstrumentId instrument, int count, Token &&token)
Forwards a recent-execution request.
static auto order_history(Client &client, const Account &account, HistoryQuery query, Token &&token)
Forwards an order-history inquiry for the bound account.
static auto place_order(Client &client, const Account &account, OrderRequest order, Token &&token)
Forwards an order submission for the bound account.
kiwoom::Broker BrokerTag
The broker tag.
static auto accounts(Client &client, Token &&token)
Forwards an account listing request.
kiwoom::KiwoomConfig Config
Kiwoom application credentials and environment selection.
kiwoom::KiwoomOpenOrderPage WorkingOrdersResult
Kiwoom amendable-order result.
static auto depth(Client &client, InstrumentId instrument, Token &&token)
Forwards an order book request.
kiwoom::KiwoomAccount Account
Kiwoom account selector, which carries nothing because Kiwoom takes nothing.
static auto working_orders(Client &client, const Account &account, Token &&token)
Forwards an amendable-order inquiry for the bound account.
static const network::RateLimitStats * rate_limit_stats(const Client &client)
Returns the rate limiter's statistics.
kiwoom::KiwoomOrderAck PlaceAck
Acknowledgement Kiwoom returns for an order instruction.
kiwoom::KiwoomHistoryQuery HistoryQuery
Kiwoom order-history selector.
static auto replace_order(Client &client, const Account &account, Amendment amendment, Token &&token)
Forwards an order modification 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.
static auto instrument(Client &client, InstrumentId subject, Token &&token)
Forwards a reference-data request.
kiwoom::KiwoomClient Client
The client type.
static constexpr Venue effective_route(Venue asked) noexcept
Returns the venue an order reaches; see kiwoom_route.
kiwoom::KiwoomAmendment Amendment
Kiwoom modification and cancellation instruction.
kiwoom::KiwoomAccountInfo AccountListItem
Item type of the broker's own account listing.
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.
An order's type, price, trigger, time in force and session, as an amendment states them.
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".
std::optional< Decimal64 > trigger_price_
The trigger price, for STOP_LIMIT.
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 Kiwoom broker tag: order references are typed by it, so a Kiwoom reference works with both Kiwoom...
static constexpr std::string_view name
The broker's name.
One account Kiwoom's ka00001 reports for the bound credential.
std::string account_number_
The account number as Kiwoom reported it, for display.
The Kiwoom account selector, which is empty: no Kiwoom endpoint takes an account number,...
An amendment or cancellation of a Kiwoom order.
Venue venue_
The venue the order rests on, as listed (Kiwoom's dmst_stex_tp): KRX, NXT or COMBINED (SOR)....
KiwoomOrderRef order_
The order to amend, which carries the symbol Kiwoom requires beside the order number.
Decimal64 quantity_
The quantity affected, or zero for everything still resting (Kiwoom evaluates 0 when it processes the...
std::optional< Decimal64 > price_
The new price, on a modification; absent on an unpriced basis, and refused on a cancellation.
std::optional< Decimal64 > condition_price_
The new trigger price (mdfy_cond_uv), for amending a stop-limit (28) order; must be empty on a cancel...
Kiwoom credentials (app key and secret key), demo or real account, the market-data tape,...
KiwoomPositionScope holdings_position_scope_
Your assertion of what holdings_venue_ means for the positions listed. No default: until it is set,...
A Kiwoom order-history query: one date (kt00007 takes no range, so a multi-day query is refused).
Date date_
The single 주문일자 to list.
std::string symbol_
Restrict to one symbol, which Kiwoom expresses as stk_cd. Empty lists every symbol.
One page of Kiwoom orders that remain modifiable or cancellable.
Kiwoom's acknowledgement of an accepted order, amendment or cancellation.
A Kiwoom order's address: order number and symbol, both of which amendments and cancellations require...
std::string order_number_
Kiwoom's ord_no.
std::string symbol_
Kiwoom's stk_cd, which its amendment endpoints require beside the order number.
A rate limiter's counters per traffic class, its current budget, and the broker's refusals (from Rate...