From 725fb452ecf6646e1714c77208705b988e1cc8cf Mon Sep 17 00:00:00 2001 From: Mark Ross <6730333+krazkidd@users.noreply.github.com> Date: Sun, 21 Jul 2024 15:24:20 -0700 Subject: [PATCH] Add portfolio API code generators, wrapper methods, and request/response types. (#64) --- include/api/Api.hpp | 8 ++ include/api/_Api.hpp | 56 ++++++++++ include/api/types.hpp | 227 ++++++++++++++++++++++++++++++++++++++ src/api/Api.portfolio.cpp | 143 ++++++++++++++++++++++++ 4 files changed, 434 insertions(+) diff --git a/include/api/Api.hpp b/include/api/Api.hpp index 3b5b941..feb7662 100644 --- a/include/api/Api.hpp +++ b/include/api/Api.hpp @@ -43,7 +43,15 @@ namespace kdeck // portfolio double GetBalance(); + std::shared_ptr GetFills(); + std::shared_ptr GetOrders(); + std::shared_ptr CreateOrder(); + std::shared_ptr GetOrder(std::string_view orderId); + std::shared_ptr CancelOrder(std::string_view orderId); + std::shared_ptr AmendOrder(std::string_view orderId); + std::shared_ptr DecreaseOrder(std::string_view orderId); std::shared_ptr GetPositions(); + std::shared_ptr GetPortfolioSettlements(); // helpers bool IsLoggedIn(); diff --git a/include/api/_Api.hpp b/include/api/_Api.hpp index bc9173b..40cee17 100644 --- a/include/api/_Api.hpp +++ b/include/api/_Api.hpp @@ -122,6 +122,55 @@ namespace kdeck } API_CALL("GET", "{basePath}/portfolio/balance", GetBalance, PATH(String, basePath), AUTHORIZATION(String, authString, "Bearer")) + API_CALL_HEADERS(GetFills) + { + headers.put("Content-Type", "application/json"); + headers.put("Accept", "application/json"); + } + API_CALL("GET", "{basePath}/portfolio/fills", GetFills, PATH(String, basePath), AUTHORIZATION(String, authString, "Bearer"), BODY_DTO(Object, req)) + + API_CALL_HEADERS(GetOrders) + { + headers.put("Content-Type", "application/json"); + headers.put("Accept", "application/json"); + } + API_CALL("GET", "{basePath}/portfolio/orders", GetOrders, PATH(String, basePath), AUTHORIZATION(String, authString, "Bearer"), BODY_DTO(Object, req)) + + API_CALL_HEADERS(CreateOrder) + { + headers.put("Content-Type", "application/json"); + headers.put("Accept", "application/json"); + } + API_CALL("POST", "{basePath}/portfolio/orders", CreateOrder, PATH(String, basePath), AUTHORIZATION(String, authString, "Bearer"), BODY_DTO(Object, req)) + + API_CALL_HEADERS(GetOrder) + { + headers.put("Content-Type", "application/json"); + headers.put("Accept", "application/json"); + } + API_CALL("GET", "{basePath}/portfolio/orders/{order_id}", GetOrder, PATH(String, basePath), AUTHORIZATION(String, authString, "Bearer"), PATH(String, order_id)) + + API_CALL_HEADERS(CancelOrder) + { + headers.put("Content-Type", "application/json"); + headers.put("Accept", "application/json"); + } + API_CALL("DELETE", "{basePath}/portfolio/orders/{order_id}", CancelOrder, PATH(String, basePath), AUTHORIZATION(String, authString, "Bearer"), PATH(String, order_id)) + + API_CALL_HEADERS(AmendOrder) + { + headers.put("Content-Type", "application/json"); + headers.put("Accept", "application/json"); + } + API_CALL("POST", "{basePath}/portfolio/orders/{order_id}/amend", AmendOrder, PATH(String, basePath), AUTHORIZATION(String, authString, "Bearer"), PATH(String, order_id), BODY_DTO(Object, req)) + + API_CALL_HEADERS(DecreaseOrder) + { + headers.put("Content-Type", "application/json"); + headers.put("Accept", "application/json"); + } + API_CALL("POST", "{basePath}/portfolio/orders/{order_id}/decrease", DecreaseOrder, PATH(String, basePath), AUTHORIZATION(String, authString, "Bearer"), PATH(String, order_id), BODY_DTO(Object, req)) + API_CALL_HEADERS(GetPositions) { headers.put("Content-Type", "application/json"); @@ -129,6 +178,13 @@ namespace kdeck } API_CALL("GET", "{basePath}/portfolio/positions", GetPositions, PATH(String, basePath), AUTHORIZATION(String, authString, "Bearer"), BODY_DTO(Object, portfolioPositionsRequest)) + API_CALL_HEADERS(GetPortfolioSettlements) + { + headers.put("Content-Type", "application/json"); + headers.put("Accept", "application/json"); + } + API_CALL("GET", "{basePath}/portfolio/settlements", GetPortfolioSettlements, PATH(String, basePath), AUTHORIZATION(String, authString, "Bearer"), BODY_DTO(Object, req)) + }; #include OATPP_CODEGEN_END(ApiClient) diff --git a/include/api/types.hpp b/include/api/types.hpp index 815b9bb..fcc688c 100644 --- a/include/api/types.hpp +++ b/include/api/types.hpp @@ -526,6 +526,194 @@ namespace kdeck }; + class FillsRequest + : public oatpp::DTO + { + + DTO_INIT(FillsRequest, DTO /* extends */) + + DTO_FIELD(String, ticker); + DTO_FIELD(String, order_id); + DTO_FIELD(Int64, min_ts); + DTO_FIELD(Int64, max_ts); + DTO_FIELD(Int32, limit); + DTO_FIELD(String, cursor); + + }; + + class Fill + : public oatpp::DTO + { + + DTO_INIT(Fill, DTO /* extends */) + + DTO_FIELD(String, action); + DTO_FIELD(Int32, count); + DTO_FIELD(DateTime_Iso8601, created_time); + DTO_FIELD(Boolean, is_taker); + DTO_FIELD(Int64, no_price); + DTO_FIELD(String, order_id); + DTO_FIELD(String, side); + DTO_FIELD(String, ticker); + DTO_FIELD(Int64, yes_price); + + }; + + class FillsResponse + : public oatpp::DTO + { + + DTO_INIT(FillsResponse, DTO /* extends */) + + DTO_FIELD(String, cursor); + DTO_FIELD(Object, fills); + + }; + + class OrdersRequest + : public oatpp::DTO + { + + DTO_INIT(OrdersRequest, DTO /* extends */) + + DTO_FIELD(String, ticker); + DTO_FIELD(String, event_ticker); + DTO_FIELD(Int64, min_ts); + DTO_FIELD(Int64, max_ts); + DTO_FIELD(String, status); + DTO_FIELD(String, cursor); + DTO_FIELD(Int32, limit); + + }; + + class Order + : public oatpp::DTO + { + + DTO_INIT(Order, DTO /* extends */) + + DTO_FIELD(String, action); + DTO_FIELD(Int32, amend_count); + DTO_FIELD(Int32, amend_taker_fill_count); + DTO_FIELD(String, client_order_id); + DTO_FIELD(Int32, close_cancel_count); + DTO_FIELD(DateTime_Iso8601, created_time); + DTO_FIELD(Int32, decrease_count); + DTO_FIELD(DateTime_Iso8601, expiration_time); + DTO_FIELD(Int32, fcc_cancel_count); + DTO_FIELD(DateTime_Iso8601, last_update_time); + DTO_FIELD(Int64, maker_fees); + DTO_FIELD(Int64, maker_fill_cost); + DTO_FIELD(Int32, maker_fill_count); + DTO_FIELD(Int64, no_price); + DTO_FIELD(String, order_id); + DTO_FIELD(Int32, place_count); + DTO_FIELD(Int32, queue_position); + DTO_FIELD(Int32, remaining_count); + DTO_FIELD(String, side); + DTO_FIELD(String, status); + DTO_FIELD(Int64, taker_fees); + DTO_FIELD(Int64, taker_fill_cost); + DTO_FIELD(Int32, taker_fill_count); + DTO_FIELD(Int32, taker_self_trade_cancel_count); + DTO_FIELD(String, ticker); + DTO_FIELD(String, type); + DTO_FIELD(String, user_id); + DTO_FIELD(Int64, yes_price); + + }; + + class OrdersResponse + : public oatpp::DTO + { + + DTO_INIT(OrdersResponse, DTO /* extends */) + + DTO_FIELD(String, cursor); + DTO_FIELD(List>, orders); + + }; + + class CreateOrderRequest + : public oatpp::DTO + { + + DTO_INIT(CreateOrderRequest, DTO /* extends */) + + DTO_FIELD(String, action); + DTO_FIELD(Int64, buy_max_cost); + DTO_FIELD(String, client_order_id); + DTO_FIELD(Int32, count); + DTO_FIELD(Int64, expiration_ts); + DTO_FIELD(Int64, no_price); + DTO_FIELD(Int32, sell_position_floor); + DTO_FIELD(String, side); + DTO_FIELD(String, ticker); + DTO_FIELD(String, type); + DTO_FIELD(Int64, yes_price); + + }; + + class OrderResponse + : public oatpp::DTO + { + + DTO_INIT(OrderResponse, DTO /* extends */) + + DTO_FIELD(Object, order); + + }; + + class CancelOrderResponse + : public oatpp::DTO + { + + DTO_INIT(CancelOrderResponse, DTO /* extends */) + + DTO_FIELD(Object, order); + DTO_FIELD(Int32, reduced_by); + + }; + + class AmendOrderRequest + : public oatpp::DTO + { + + DTO_INIT(AmendOrderRequest, DTO /* extends */) + + DTO_FIELD(String, action); + DTO_FIELD(String, client_order_id); + DTO_FIELD(Int32, count); + DTO_FIELD(Int64, no_price); + DTO_FIELD(String, side); + DTO_FIELD(String, ticker); + DTO_FIELD(String, updated_client_order_id); + DTO_FIELD(Int64, yes_price); + + }; + + class AmendOrderResponse + : public oatpp::DTO + { + + DTO_INIT(AmendOrderResponse, DTO /* extends */) + + DTO_FIELD(Object, old_order); + DTO_FIELD(Object, order); + + }; + + class DecreaseOrderRequest + : public oatpp::DTO + { + + DTO_INIT(DecreaseOrderRequest, DTO /* extends */) + + DTO_FIELD(Int32, reduce_by); + DTO_FIELD(Int32, reduce_to); + + }; + struct PortfolioPositionsRequest : public oatpp::DTO { @@ -584,6 +772,45 @@ namespace kdeck }; + class PortfolioSettlementsRequest + : public oatpp::DTO + { + + DTO_INIT(PortfolioSettlementsRequest, DTO /* extends */) + + DTO_FIELD(Int64, limit); + DTO_FIELD(String, cursor); + + }; + + class Settlement + : public oatpp::DTO + { + + DTO_INIT(Settlement, DTO /* extends */) + + DTO_FIELD(String, market_result); + DTO_FIELD(Int64, no_count); + DTO_FIELD(Int64, no_total_cost); + DTO_FIELD(Int64, revenue); + DTO_FIELD(DateTime_Iso8601, settled_time); + DTO_FIELD(String, ticker); + DTO_FIELD(Int64, yes_count); + DTO_FIELD(Int64, yes_total_cost); + + }; + + class PortfolioSettlementsResponse + : public oatpp::DTO + { + + DTO_INIT(PortfolioSettlementsResponse, DTO /* extends */) + + DTO_FIELD(String, cursor); + DTO_FIELD(Object, settlements); + + }; + #include OATPP_CODEGEN_END(DTO) } diff --git a/src/api/Api.portfolio.cpp b/src/api/Api.portfolio.cpp index 68877cd..0cf7927 100644 --- a/src/api/Api.portfolio.cpp +++ b/src/api/Api.portfolio.cpp @@ -29,6 +29,128 @@ namespace kdeck return balance->balance; } + std::shared_ptr Api::GetOrders() + { + OATPP_LOGD("Api", "GetOrders"); + + auto req = OrdersRequest::createShared(); + + ApiResult res = HandleResponse(_api->GetOrders(basePath, login->token, req)); + + if (std::holds_alternative>(res)) + { + //TODO populate orders + return std::get>(res); + } + else + { + throw std::runtime_error(std::get>(res)->error->message->c_str()); + } + + //TODO return orders; + } + + std::shared_ptr Api::CreateOrder() + { + OATPP_LOGD("Api", "CreateOrder"); + + auto req = CreateOrderRequest::createShared(); + + ApiResult res = HandleResponse(_api->CreateOrder(basePath, login->token, req)); + + if (std::holds_alternative>(res)) + { + //TODO populate orders + return std::get>(res); + } + else + { + throw std::runtime_error(std::get>(res)->error->message->c_str()); + } + + //TODO return order; + } + + std::shared_ptr Api::GetOrder(std::string_view orderId) + { + OATPP_LOGD("Api", "GetOrder"); + + ApiResult res = HandleResponse(_api->GetOrder(basePath, login->token, std::string{orderId})); + + if (std::holds_alternative>(res)) + { + //TODO populate orders + return std::get>(res); + } + else + { + throw std::runtime_error(std::get>(res)->error->message->c_str()); + } + + //TODO return order; + } + + std::shared_ptr Api::CancelOrder(std::string_view orderId) + { + OATPP_LOGD("Api", "CancelOrder"); + + ApiResult res = HandleResponse(_api->CancelOrder(basePath, login->token, std::string{orderId})); + + if (std::holds_alternative>(res)) + { + //TODO depopulate orders; this can return a partially filled order! + return std::get>(res); + } + else + { + throw std::runtime_error(std::get>(res)->error->message->c_str()); + } + + //TODO return order; + } + + std::shared_ptr Api::AmendOrder(std::string_view orderId) + { + OATPP_LOGD("Api", "AmendOrder"); + + auto req = AmendOrderRequest::createShared(); + + ApiResult res = HandleResponse(_api->AmendOrder(basePath, login->token, std::string{orderId}, req)); + + if (std::holds_alternative>(res)) + { + //TODO populate orders + return std::get>(res); + } + else + { + throw std::runtime_error(std::get>(res)->error->message->c_str()); + } + + //TODO return order; + } + + std::shared_ptr Api::DecreaseOrder(std::string_view orderId) + { + OATPP_LOGD("Api", "DecreaseOrder"); + + auto req = DecreaseOrderRequest::createShared(); + + ApiResult res = HandleResponse(_api->DecreaseOrder(basePath, login->token, std::string{orderId}, req)); + + if (std::holds_alternative>(res)) + { + //TODO populate orders + return std::get>(res); + } + else + { + throw std::runtime_error(std::get>(res)->error->message->c_str()); + } + + //TODO return order; + } + std::shared_ptr Api::GetPositions() { OATPP_LOGD("Api", "GetPositions"); @@ -69,6 +191,27 @@ namespace kdeck return positions; } + std::shared_ptr Api::GetPortfolioSettlements() + { + OATPP_LOGD("Api", "GetPortfolioSettlements"); + + auto req = PortfolioSettlementsRequest::createShared(); + + ApiResult res = HandleResponse(_api->GetPortfolioSettlements(basePath, login->token, req)); + + if (std::holds_alternative>(res)) + { + //TODO populate settlements + return std::get>(res); + } + else + { + throw std::runtime_error(std::get>(res)->error->message->c_str()); + } + + //TODO return settlements; + } + // helpers ///////////////////////////////////////////////////////////////////// std::list> Api::GetEventPositions()