kalshi-cpp 0.6.2
C++23 client for Kalshi's Predictions API
Loading...
Searching...
No Matches
fixed_point.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "kalshi/error.hpp"
4
5#include <cstdint>
6#include <limits>
7#include <string>
8#include <string_view>
9
10namespace kalshi {
11
14public:
15 [[nodiscard]] static Result<FixedPoint> parse(std::string_view value) {
16 if (value.empty()) {
17 return std::unexpected(
18 Error{ErrorCode::InvalidRequest, "fixed-point value is empty", 0, {}});
19 }
20
21 std::size_t index = value.front() == '-' ? 1 : 0;
22 if (index == value.size()) {
23 return std::unexpected(
24 Error{ErrorCode::InvalidRequest, "fixed-point value has no digits", 0, {}});
25 }
26
27 bool saw_digit = false;
28 bool saw_decimal = false;
29 bool fractional_digit = false;
30 for (; index < value.size(); ++index) {
31 const char ch = value[index];
32 if (ch >= '0' && ch <= '9') {
33 saw_digit = true;
34 fractional_digit = fractional_digit || saw_decimal;
35 continue;
36 }
37 if (ch == '.' && !saw_decimal && saw_digit) {
38 saw_decimal = true;
39 continue;
40 }
41 return std::unexpected(
42 Error{ErrorCode::InvalidRequest, "invalid fixed-point value", 0, {}});
43 }
44 if (!saw_digit || (saw_decimal && !fractional_digit)) {
45 return std::unexpected(
46 Error{ErrorCode::InvalidRequest, "invalid fixed-point value", 0, {}});
47 }
48 return FixedPoint(std::string(value));
49 }
50
51 [[nodiscard]] const std::string& wire() const noexcept { return wire_; }
52
55 [[nodiscard]] Result<std::int64_t> scaled_integer(std::uint8_t scale) const {
56 if (scale > 18) {
57 return std::unexpected(Error{
58 ErrorCode::InvalidRequest, "fixed-point scale exceeds int64 capacity", 0, {}});
59 }
60
61 const bool negative = wire_.front() == '-';
62 const std::size_t first = negative ? 1 : 0;
63 const std::size_t decimal = wire_.find('.', first);
64 const std::size_t whole_end = decimal == std::string::npos ? wire_.size() : decimal;
65 const std::size_t fractional_start =
66 decimal == std::string::npos ? wire_.size() : decimal + 1;
67 const std::size_t fractional_size = wire_.size() - fractional_start;
68
69 if (fractional_size > scale) {
70 for (std::size_t i = fractional_start + scale; i < wire_.size(); ++i) {
71 if (wire_[i] != '0') {
72 return std::unexpected(Error{ErrorCode::InvalidRequest,
73 "fixed-point conversion would lose precision",
74 0,
75 {}});
76 }
77 }
78 }
79
80 const std::uint64_t positive_limit =
81 negative ? std::uint64_t{std::numeric_limits<std::int64_t>::max()} + 1U
82 : std::uint64_t{std::numeric_limits<std::int64_t>::max()};
83 std::uint64_t magnitude = 0;
84 const auto append_digit = [&](char ch) -> bool {
85 const std::uint64_t digit = static_cast<std::uint64_t>(ch - '0');
86 if (magnitude > (positive_limit - digit) / 10U) {
87 return false;
88 }
89 magnitude = magnitude * 10U + digit;
90 return true;
91 };
92
93 for (std::size_t i = first; i < whole_end; ++i) {
94 if (!append_digit(wire_[i])) {
95 return overflow_error();
96 }
97 }
98 for (std::uint8_t i = 0; i < scale; ++i) {
99 const char digit = i < fractional_size ? wire_[fractional_start + i] : '0';
100 if (!append_digit(digit)) {
101 return overflow_error();
102 }
103 }
104
105 if (negative && magnitude == positive_limit) {
106 return std::numeric_limits<std::int64_t>::min();
107 }
108 const std::int64_t signed_value = static_cast<std::int64_t>(magnitude);
109 return negative ? -signed_value : signed_value;
110 }
111
112private:
113 explicit FixedPoint(std::string wire) : wire_(std::move(wire)) {}
114
115 [[nodiscard]] static Result<std::int64_t> overflow_error() {
116 return std::unexpected(
117 Error{ErrorCode::InvalidRequest, "fixed-point value does not fit in int64", 0, {}});
118 }
119
120 std::string wire_;
121};
122
123} // namespace kalshi
Lossless fixed-point decimal received from or sent to Kalshi.
Definition fixed_point.hpp:13
static Result< FixedPoint > parse(std::string_view value)
Definition fixed_point.hpp:15
const std::string & wire() const noexcept
Definition fixed_point.hpp:51
Result< std::int64_t > scaled_integer(std::uint8_t scale) const
Convert exactly to an integer with scale decimal places.
Definition fixed_point.hpp:55
Definition api.hpp:15
std::expected< T, Error > Result
Result type for SDK operations.
Definition error.hpp:50
@ InvalidRequest
Rejected before sending, or another HTTP 4xx.
Definition error.hpp:23