algotradelib 0.0.0.9000
C++ header-only library for algorithmic trading
Loading...
Searching...
No Matches
example-kis-orders.cpp
1#include "kis_credentials.hpp"
2
3#include <algotradelib/kis>
4
5#include <boost/asio/ssl/context.hpp>
6
7#include <chrono>
8#include <cstdlib>
9#include <ctime>
10#include <exception>
11#include <iostream>
12#include <string>
13#include <string_view>
14#include <utility>
15
16namespace ssl = boost::asio::ssl;
17namespace atl = algotradelib;
18
19namespace {
20
22void print_error(std::string_view operation, const atl::BrokerError& error) {
23 std::cerr << operation << " failed";
24 if (!error.broker_code_.empty()) {
25 std::cerr << " [" << error.broker_code_ << ']';
26 }
27 if (error.http_status_ != 0) {
28 std::cerr << " HTTP " << error.http_status_;
29 }
30 if (!error.message_.empty()) {
31 std::cerr << ": " << error.message_;
32 }
33 std::cerr << '\n';
35 std::cerr
36 << " the outcome is indeterminate; reconcile through the order inquiries "
37 "before resubmitting\n";
38 }
39}
40
42std::string_view status_name(atl::OrderStatus status) {
43 switch (status) {
44 case atl::OrderStatus::PENDING:
45 return "PENDING";
46 case atl::OrderStatus::PENDING_CANCEL:
47 return "PENDING_CANCEL";
48 case atl::OrderStatus::PENDING_REPLACE:
49 return "PENDING_REPLACE";
50 case atl::OrderStatus::PARTIAL_FILLED:
51 return "PARTIAL_FILLED";
52 case atl::OrderStatus::FILLED:
53 return "FILLED";
54 case atl::OrderStatus::CANCELED:
55 return "CANCELED";
56 case atl::OrderStatus::REJECTED:
57 return "REJECTED";
58 case atl::OrderStatus::CANCEL_REJECTED:
59 return "CANCEL_REJECTED";
60 case atl::OrderStatus::REPLACE_REJECTED:
61 return "REPLACE_REJECTED";
62 case atl::OrderStatus::REPLACED:
63 return "REPLACED";
64 default:
65 return "UNKNOWN";
66 }
67}
68
70void print_order(const atl::OrderSnapshot& order) {
71 std::cout << order.order_id_ << " " << order.instrument_.symbol_ << " " << order.name_ << '\n';
72 std::cout << " " << (order.side_ == atl::OrderSide::BUY ? "BUY" : "SELL") << " "
73 << status_name(order.status_) << " quantity " << order.quantity_.str();
74 if (order.price_) {
75 std::cout << " @ " << order.price_->str();
76 }
77 std::cout << '\n';
78 std::cout << " filled: " << order.execution_.filled_quantity_.str();
80 std::cout << " @ average " << order.execution_.average_filled_price_->str();
81 }
82 std::cout << '\n';
83}
84
86atl::Date today() {
87 const auto now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
88 std::tm local{};
89#ifdef _WIN32
90 localtime_s(&local, &now);
91#else
92 localtime_r(&now, &local);
93#endif
94 return atl::Date{
95 local.tm_year + 1900,
96 static_cast<unsigned>(local.tm_mon + 1),
97 static_cast<unsigned>(local.tm_mday),
98 };
99}
100
101} // namespace
102
104int main(int argc, char* argv[]) {
105 try {
106 atl::kis::KisConfig config;
107 atl::kis::KisAccount account;
108 kis_credentials::load(kis_credentials::take_directory(argc, argv), config, &account, std::cout);
109 const bool demo = config.is_demo_;
110
111 std::cout << "environment: " << (demo ? "demo" : "live") << '\n';
112
113 ssl::context tls(ssl::context::tls_client);
114 tls.set_default_verify_paths();
115 tls.set_verify_mode(ssl::verify_peer);
116
117 atl::kis::KisBlockingClient client(tls, std::move(config), kis_credentials::paced_options());
118
119 // On demo KIS has no modifiable-order inquiry, and the client answers this read from today's
120 // order history instead.
121 {
122 auto open_result = client.open_orders(account);
123 if (!open_result) {
124 print_error("modifiable-order inquiry", open_result.error());
125 return 1;
126 }
127 std::cout << "open orders" << (demo ? " (from today's history)" : "") << ": "
128 << open_result.value().orders_.size() << '\n';
129 for (const auto& open_order : open_result.value().orders_) {
130 print_order(open_order.order_);
131 std::cout << " amendable quantity: " << open_order.amendable_quantity_.str()
132 << " branch " << open_order.order_ref_.branch_number_ << '\n';
133 }
134 }
135
136 const auto day = today();
137 auto history_result = client.order_history(account, atl::kis::KisHistoryRange{day, day});
138 if (!history_result) {
139 print_error("order-history inquiry", history_result.error());
140 return 1;
141 }
142 std::cout << "orders today: " << history_result.value().orders_.size() << '\n';
143 for (const auto& order : history_result.value().orders_) {
144 print_order(order);
145 }
146 return 0;
147 } catch (const std::exception& exception) {
148 std::cerr << "example failed: " << exception.what() << '\n';
149 return 1;
150 }
151}
std::string str() const
Formats the value as a decimal string.
Definition types.hpp:411
A blocking KIS client: each call runs a KisClient request on a private event loop and returns its res...
Definition client.hpp:4540
The examples' KIS credentials: one JSON file per account, or the environment.
algotradelib::network::HttpClientOptions paced_options()
Returns transport options that pace a KIS client at one request a second.
void load(const std::optional< std::filesystem::path > &directory, algotradelib::kis::KisConfig &config, algotradelib::kis::KisAccount *account, std::ostream &out)
Loads the credentials (and account) KIS_DEMO chooses, and prints where from (a path or "environment v...
std::optional< std::filesystem::path > take_directory(int &argc, char **argv)
Removes --credentials DIR from the command line and returns the directory, else ATL_CREDENTIALS_DIR.
The library: broker-neutral types (core), and the modules below.
OrderStatus
Where an order stands in its lifecycle.
Definition types.hpp:1879
@ TRANSPORT
The connection failed (DNS, connect, TLS, write or read).
Definition types.hpp:691
int http_status_
The HTTP status of the reply: set for an HTTP error and for a reply whose body is not a JSON object....
Definition types.hpp:759
std::string message_
A human-readable description, for logs; do not parse it.
Definition types.hpp:772
ErrorCategory category_
The kind of failure; the field to branch on.
Definition types.hpp:744
std::string broker_code_
The broker's own error code, verbatim (for example KIS's EGW00201).
Definition types.hpp:761
std::string symbol_
The symbol as the venue spells it, such as "005930".
Definition types.hpp:88
Decimal64 filled_quantity_
The quantity filled so far; zero if nothing has filled. Always present.
Definition types.hpp:1983
std::optional< Decimal64 > average_filled_price_
The average fill price, only where the broker supplies it.
Definition types.hpp:1990
OrderSide side_
Buy or sell.
Definition types.hpp:2016
OrderStatus status_
The status; UNKNOWN where the broker publishes none.
Definition types.hpp:2038
OrderExecution execution_
What has filled and what it cost; see OrderExecution before testing a fill.
Definition types.hpp:2074
std::string name_
The instrument's name as the broker spells it.
Definition types.hpp:2014
Decimal64 quantity_
The quantity ordered; the remainder is this minus execution_.filled_quantity_.
Definition types.hpp:2050
std::string order_id_
The broker's order number.
Definition types.hpp:2010
InstrumentId instrument_
The instrument (identity venue; the routing venue is venue_).
Definition types.hpp:2012
std::optional< Decimal64 > price_
The limit price, if the order has one.
Definition types.hpp:2040
A KIS account: the account number and product code every account request names.
Definition client.hpp:29
KIS credentials (app key and secret), demo or real account, and the market-data tape.
Definition config.hpp:90
bool is_demo_
Whether to use KIS's demo (모의투자) endpoints; true unless stated otherwise.
Definition config.hpp:101
The date range of a KIS order-history inquiry, both ends included (Korean dates).
Definition client.hpp:189