├── tests ├── mock_custom │ ├── invalidate_session.json │ ├── convert_position.json │ ├── websocket_ticks.bin │ └── generate_session.json └── unit │ ├── kitepp.hpp │ ├── main.cpp │ ├── utils.hpp │ ├── kite │ ├── api.cpp │ ├── user.cpp │ ├── gtt.cpp │ └── margins.cpp │ └── tickertest.cpp ├── .git-blame-ignore-revs ├── .gitignore ├── .clang-tidy ├── Dockerfile ├── cmake ├── templates │ └── Doxyfile.in └── modules │ └── FindGMock.cmake ├── .github ├── ISSUE_TEMPLATE │ └── bug_report.md └── workflows │ └── cppkiteconnect-test.yml ├── .gitmodules ├── LICENSE ├── include ├── kitepp │ ├── ticker.hpp │ ├── responses │ │ ├── responses.hpp │ │ ├── ws.hpp │ │ ├── gtt.hpp │ │ ├── margins.hpp │ │ ├── user.hpp │ │ ├── portfolio.hpp │ │ ├── order.hpp │ │ └── market.hpp │ ├── kite │ │ ├── kite.hpp │ │ ├── user.hpp │ │ ├── portfolio.hpp │ │ ├── api.hpp │ │ ├── internal.hpp │ │ ├── margins.hpp │ │ ├── market.hpp │ │ ├── gtt.hpp │ │ ├── mf.hpp │ │ └── order.hpp │ ├── userconstants.hpp │ ├── exceptions.hpp │ └── ticker │ │ └── ws.hpp └── kitepp.hpp ├── .clang-format ├── deps └── CMakeLists.txt ├── examples ├── example1.cpp ├── example3.cpp └── example4.cpp ├── docs ├── header.html └── mainpage.md ├── CMakeLists.txt └── README.md /tests/mock_custom/invalidate_session.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "success", 3 | "data": true 4 | } -------------------------------------------------------------------------------- /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | # change column limit to 80 2 | 39cd0478af477b63ecc925fa8af8b0c82e4566e6 3 | -------------------------------------------------------------------------------- /tests/mock_custom/convert_position.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "success", 3 | "data": true 4 | } 5 | -------------------------------------------------------------------------------- /tests/mock_custom/websocket_ticks.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zerodha/cppkiteconnect/HEAD/tests/mock_custom/websocket_ticks.bin -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #build files 2 | build/ 3 | 4 | #VS Code auto generated files 5 | .cache/ 6 | .clangd/ 7 | .vscode/ 8 | compile_commands.json 9 | 10 | #generated docs 11 | !docs/config.doxygen 12 | !docs/mainpage.dox 13 | !docs/CMakeLists.txt 14 | 15 | #downloaded dependancies 16 | deps/** 17 | !deps/CMakeLists.txt 18 | 19 | 20 | -------------------------------------------------------------------------------- /.clang-tidy: -------------------------------------------------------------------------------- 1 | Checks: '*, -modernize-use-trailing-return-type, -fuchsia*, -google-runtime-references, -google-readability-todo, -llvmlibc-*, -altera*, -readability-function-cognitive-complexity, -misc-non-private-member-variables-in-classes, -cppcoreguidelines-non-private-member-variables-in-classes, -cppcoreguidelines-pro-bounds-pointer-arithmetic' 2 | CheckOptions: 3 | - key: 'misc-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic' 4 | value: 'true' -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM fedora:38 2 | 3 | # install dependencies 4 | WORKDIR /opt 5 | RUN dnf update -y && \ 6 | dnf install -y cmake gcc-c++ make openssl-devel zlib-devel libuv-devel git && \ 7 | git clone https://github.com/hoytech/uWebSockets.git && \ 8 | cd uWebSockets && \ 9 | make && \ 10 | make install && \ 11 | cd .. && \ 12 | dnf clean all 13 | # setup repo 14 | WORKDIR /app 15 | COPY . /app 16 | RUN git submodule update --init --recursive && \ 17 | rm -rf build 18 | # build the project 19 | RUN mkdir build && \ 20 | cd build && \ 21 | cmake .. -DBUILD_EXAMPLES=On && \ 22 | make 23 | # run the example 24 | ENTRYPOINT ["sh", "-c", "./build/example$EXAMPLE_NUMBER"] 25 | -------------------------------------------------------------------------------- /cmake/templates/Doxyfile.in: -------------------------------------------------------------------------------- 1 | PROJECT_NAME = "CPPKiteConnect" 2 | OUTPUT_DIRECTORY = "@CMAKE_CURRENT_BINARY_DIR@/docs/" 3 | INPUT = "@CMAKE_SOURCE_DIR@/include/kitepp" "@CMAKE_SOURCE_DIR@/include/kitepp.hpp" "@CMAKE_SOURCE_DIR@/docs/mainpage.md" 4 | RECURSIVE = YES 5 | EXAMPLE_PATH = "@CMAKE_SOURCE_DIR@/examples" 6 | GENERATE_HTML = YES 7 | USE_MDFILE_AS_MAINPAGE = "mainpage.md" 8 | EXCLUDE_SYMBOLS = "internal" 9 | ENABLE_PREPROCESSING = YES 10 | MACRO_EXPANSION = YES 11 | 12 | GENERATE_TREEVIEW = YES 13 | DISABLE_INDEX = NO 14 | FULL_SIDEBAR = NO 15 | HTML_EXTRA_STYLESHEET = "@CMAKE_SOURCE_DIR@/docs/doxygen-awesome-css/doxygen-awesome.css" 16 | HTML_EXTRA_FILES = "@CMAKE_SOURCE_DIR@/docs/doxygen-awesome-css/doxygen-awesome-darkmode-toggle.js" 17 | HTML_HEADER = "@CMAKE_SOURCE_DIR@/docs/header.html" 18 | -------------------------------------------------------------------------------- /tests/mock_custom/generate_session.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "success", 3 | "data": { 4 | "user_id": "XX000", 5 | "user_name": "Kite Connect", 6 | "user_shortname": "Kite", 7 | "email": "kite@kite.trade", 8 | "user_type": "investor", 9 | "broker": "ZERODHA", 10 | "exchanges": [ 11 | "MCX", 12 | "BSE", 13 | "NSE", 14 | "BFO", 15 | "NFO", 16 | "CDS" 17 | ], 18 | "products": [ 19 | "BO", 20 | "CNC", 21 | "CO", 22 | "MIS", 23 | "NRML" 24 | ], 25 | "order_types": [ 26 | "LIMIT", 27 | "MARKET", 28 | "SL", 29 | "SL-M" 30 | ], 31 | "api_key": "xxxxxx", 32 | "access_token": "yyyyyy", 33 | "public_token": "zzzzzz", 34 | "refresh_token": null, 35 | "login_time": "2018-01-01 16:15:14", 36 | "avatar_url": null 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Bug reporting template 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Before reporting any bug, please make sure that you've went through the README and you have taken proper care of dependencies, particularly uWS v0.14** 11 | 12 | **Describe the bug** 13 | A clear and concise description of what the bug is. 14 | 15 | **To Reproduce** 16 | Steps to reproduce the behavior. 17 | 18 | **Expected behavior** 19 | A clear and concise description of what you expected to happen. 20 | 21 | **Actual behavior** 22 | A clear and concise description of what actually happened. 23 | 24 | **Unit test output** 25 | Run unit tests before reporting any bug and share the output. 26 | 27 | **Machine (please complete the following information):** 28 | - OS: [e.g. Linux] 29 | - Distribution (if using Linux) [e.g, Fedora] 30 | - Version: [e.g. 32] 31 | 32 | **Dependency versions** 33 | e.g., openssl v1.1 34 | 35 | **Additional context** 36 | Add any other context about the problem here. 37 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "tests/mock_responses"] 2 | path = tests/mock_responses 3 | url = https://github.com/zerodha/kiteconnect-mocks 4 | [submodule "include/PicoSHA2"] 5 | path = include/PicoSHA2 6 | url = https://github.com/okdshin/PicoSHA2.git 7 | [submodule "include/fmt"] 8 | path = include/fmt 9 | url = https://github.com/fmtlib/fmt.git 10 | [submodule "include/rapidjson"] 11 | path = include/rapidjson 12 | url = https://github.com/Tencent/rapidjson.git 13 | [submodule "include/cpp-httplib"] 14 | path = include/cpp-httplib 15 | url = https://github.com/yhirose/cpp-httplib.git 16 | [submodule "doxygen-awesome-css"] 17 | path = doxygen-awesome-css 18 | url = https://github.com/jothepro/doxygen-awesome-css.git 19 | [submodule "docs/doxygen-awesome-css"] 20 | path = docs/doxygen-awesome-css 21 | url = https://github.com/jothepro/doxygen-awesome-css.git 22 | [submodule "include/uri-parser"] 23 | path = include/uri-parser 24 | url = https://github.com/bhumitattarde/uri-parser.git 25 | [submodule "include/rapidcsv"] 26 | path = include/rapidcsv 27 | url = https://github.com/d99kris/rapidcsv.git 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Licensed under the MIT License . 2 | SPDX-License-Identifier: MIT 3 | 4 | Copyright (c) 2020-2021 Bhumit Attarde 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /include/kitepp/ticker.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2022 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #pragma once 27 | 28 | #include "ticker/internal.hpp" 29 | #include "ticker/ws.hpp" -------------------------------------------------------------------------------- /tests/unit/kitepp.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2022 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #pragma once 27 | 28 | #define KITE_UNIT_TEST 29 | #include "../include/kitepp.hpp" 30 | #undef KITE_UNIT_TEST 31 | -------------------------------------------------------------------------------- /tests/unit/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2022 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | 28 | int main(int argc, char** argv) { 29 | ::testing::InitGoogleTest(&argc, argv); 30 | return RUN_ALL_TESTS(); 31 | } -------------------------------------------------------------------------------- /include/kitepp/responses/responses.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2022 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #pragma once 27 | 28 | #include "gtt.hpp" 29 | #include "margins.hpp" 30 | #include "market.hpp" 31 | #include "mf.hpp" 32 | #include "order.hpp" 33 | #include "portfolio.hpp" 34 | #include "user.hpp" 35 | #include "ws.hpp" -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: Microsoft 3 | AlignAfterOpenBracket: DontAlign 4 | AlignConsecutiveMacros: 'true' 5 | AlignTrailingComments: 'true' 6 | AllowAllArgumentsOnNextLine: 'true' 7 | AllowAllConstructorInitializersOnNextLine: 'true' 8 | AllowAllParametersOfDeclarationOnNextLine: 'true' 9 | AllowShortBlocksOnASingleLine: 'true' 10 | AllowShortCaseLabelsOnASingleLine: 'true' 11 | AllowShortFunctionsOnASingleLine: All 12 | AllowShortIfStatementsOnASingleLine: WithoutElse 13 | AllowShortLambdasOnASingleLine: All 14 | AllowShortLoopsOnASingleLine: 'true' 15 | AlwaysBreakBeforeMultilineStrings: 'false' 16 | AlwaysBreakTemplateDeclarations: 'Yes' 17 | BinPackArguments: 'true' 18 | BinPackParameters: 'true' 19 | BreakBeforeBraces: Attach 20 | BreakBeforeTernaryOperators: 'false' 21 | ColumnLimit: '80' 22 | CompactNamespaces: 'false' 23 | Cpp11BracedListStyle: 'false' 24 | FixNamespaceComments: 'true' 25 | IndentCaseLabels: 'true' 26 | IndentWidth: '4' 27 | IndentWrappedFunctionNames: 'true' 28 | KeepEmptyLinesAtTheStartOfBlocks: 'true' 29 | Language: Cpp 30 | NamespaceIndentation: None 31 | PointerAlignment: Left 32 | ReflowComments: 'true' 33 | SpaceAfterCStyleCast: 'true' 34 | SpaceAfterLogicalNot: 'false' 35 | SpaceBeforeAssignmentOperators: 'true' 36 | SpaceBeforeCpp11BracedList: 'true' 37 | SpaceBeforeCtorInitializerColon: 'false' 38 | SpaceBeforeInheritanceColon: 'true' 39 | SpaceBeforeParens: ControlStatements 40 | SpaceBeforeRangeBasedForLoopColon: 'true' 41 | SpaceInEmptyParentheses: 'false' 42 | SpacesInContainerLiterals: 'true' 43 | SpacesInParentheses: 'false' 44 | SpacesInSquareBrackets: 'false' 45 | TabWidth: '4' 46 | 47 | ... 48 | -------------------------------------------------------------------------------- /include/kitepp/kite/kite.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2022 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #pragma once 27 | 28 | #include "api.hpp" 29 | #include "gtt.hpp" 30 | #include "internal.hpp" 31 | #include "margins.hpp" 32 | #include "market.hpp" 33 | #include "mf.hpp" 34 | #include "order.hpp" 35 | #include "portfolio.hpp" 36 | #include "user.hpp" 37 | -------------------------------------------------------------------------------- /include/kitepp.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2022 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /** 27 | * @brief Convenience header for kitepp. This is the ONLY header that should be 28 | * included. 29 | * 30 | * @paragraph ex1 example1 31 | * @snippet example2.cpp adding kitepp header 32 | */ 33 | 34 | #pragma once 35 | 36 | #define CPPHTTPLIB_OPENSSL_SUPPORT 37 | 38 | #include "kitepp/kite.hpp" 39 | #include "kitepp/kite/kite.hpp" 40 | #include "kitepp/responses/responses.hpp" 41 | #include "kitepp/ticker.hpp" 42 | #include "kitepp/userconstants.hpp" 43 | -------------------------------------------------------------------------------- /include/kitepp/kite/user.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2022 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #pragma once 27 | #pragma clang diagnostic ignored "-Wundefined-inline" 28 | 29 | #include "../kite.hpp" 30 | #include "../utils.hpp" 31 | 32 | namespace kiteconnect { 33 | inline userProfile kite::profile() { 34 | return callApi("user.profile"); 35 | }; 36 | 37 | inline allMargins kite::getMargins() { 38 | return callApi("user.margins"); 39 | }; 40 | 41 | inline margins kite::getMargins(const string& segment) { 42 | return callApi( 43 | "user.margins.segment", {}, { segment }); 44 | }; 45 | } // namespace kiteconnect 46 | -------------------------------------------------------------------------------- /deps/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(CPPKiteConnect) 3 | 4 | function(downloadFile URL destination hashType hash) 5 | if(NOT EXISTS ${destination}) 6 | message("Downloading ${destination} ..") 7 | file(DOWNLOAD ${URL} 8 | ${destination} 9 | TIMEOUT 60 # seconds 10 | EXPECTED_HASH ${hashType}=${hash} 11 | ) 12 | else() 13 | message("${destination} already exists") 14 | endif() 15 | endfunction(downloadFile) 16 | 17 | #Download uWS v0.14 18 | downloadFile( "https://api.github.com/repos/hoytech/uWebSockets/tarball/master" 19 | "${CMAKE_SOURCE_DIR}/deps/uWebSockets.tar.gz" 20 | SHA256 21 | 40ecedbdd2fb5b6f69f06e8830e9139dc290c3125d1eb1f3449b9fd9277b50c8 22 | ) 23 | 24 | #Download GTest 25 | downloadFile( "https://github.com/google/googletest/archive/release-1.10.0.tar.gz" 26 | "${CMAKE_SOURCE_DIR}/deps/googletest-1.10.0.tar.gz" 27 | SHA256 28 | 9dc9157a9a1551ec7a7e43daea9a694a0bb5fb8bec81235d8a1e6ef64c716dcb 29 | ) 30 | 31 | #Download openssl 32 | downloadFile( "https://github.com/openssl/openssl/archive/OpenSSL_1_1_1i.tar.gz" 33 | "${CMAKE_SOURCE_DIR}/deps/OpenSSL_1_1_1i.tar.gz" 34 | SHA256 35 | 728d537d466a062e94705d44ee8c13c7b82d1b66f59f4e948e0cbf1cd7c461d8 36 | ) 37 | 38 | #Download libuv 39 | downloadFile( "https://dist.libuv.org/dist/v1.40.0/libuv-v1.40.0.tar.gz" 40 | "${CMAKE_SOURCE_DIR}/deps/libuv-v1.40.0.tar.gz" 41 | SHA256 42 | 61a90db95bac00adec1cc5ddc767ebbcaabc70242bd1134a7a6b1fb1d498a194 43 | )# Download zlib 44 | downloadFile( "https://github.com/madler/zlib/archive/v1.2.11.tar.gz" 45 | "${CMAKE_SOURCE_DIR}/deps/zlib-v1.2.11.tar.gz" 46 | SHA256 47 | 629380c90a77b964d896ed37163f5c3a34f6e6d897311f1df2a7016355c45eff 48 | ) 49 | -------------------------------------------------------------------------------- /.github/workflows/cppkiteconnect-test.yml: -------------------------------------------------------------------------------- 1 | name: CPPKiteConnect-test 2 | 3 | # Get triggered on 4 | on: 5 | push: 6 | branches: [main, v2] 7 | pull_request: 8 | branches: [main, v2] 9 | release: 10 | 11 | jobs: 12 | # This job builds and runs unit tests 13 | build-and-test: 14 | # Define a strategy 15 | strategy: 16 | # Matrix of configs to test 17 | matrix: 18 | config: 19 | - { name: ubuntu, os: ubuntu-latest } 20 | - { name: macOS, os: macos-latest } 21 | #TODO - { name: windows, os: windows-latest } 22 | 23 | name: ${{ matrix.config.name }} 24 | runs-on: ${{ matrix.config.os }} 25 | 26 | steps: 27 | # Check out repo with submodules 28 | - uses: actions/checkout@v2 29 | with: 30 | submodules: true 31 | 32 | # Build & test on Linux 33 | - name: Build and test on (Ubuntu) Linux 34 | if: startsWith(matrix.config.name, 'ubuntu') 35 | run: | 36 | sudo apt update && sudo apt -y install libssl-dev zlib1g-dev git g++ build-essential cmake googletest google-mock libgtest-dev libgmock-dev doxygen 37 | git clone https://github.com/hoytech/uWebSockets.git 38 | cd uWebSockets && make && sudo make install && cd .. 39 | mkdir build && cd build 40 | cmake .. -DBUILD_EXAMPLES=ON -DBUILD_TESTS=ON && make && make test ARGS="-V" 41 | 42 | # Build & test on macOS 43 | - name: Build and test on macOS 44 | if: startsWith(matrix.config.name, 'macOS') 45 | run: | 46 | brew extract --version=1.10.0 googletest homebrew/cask-versions && brew install googletest@1.10.0 libuv 47 | export PKG_CONFIG_PATH="/usr/local/opt/openssl/lib/pkgconfig" 48 | 49 | curl -L https://github.com/hoytech/uWebSockets/archive/refs/tags/v0.14.8.tar.gz > uWebSocketsv-0.14.8.tar.gz 50 | tar -xvf uWebSocketsv-0.14.8.tar.gz 51 | cd uWebSockets-0.14.8 52 | make && make installDarwin && cd .. 53 | 54 | mkdir build && cd build 55 | cmake .. -DBUILD_EXAMPLES=ON -DBUILD_TESTS=ON && make && make test ARGS="-V" 56 | -------------------------------------------------------------------------------- /include/kitepp/kite/portfolio.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2022 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #pragma once 27 | #pragma clang diagnostic ignored "-Wundefined-inline" 28 | 29 | #include 30 | 31 | #include "../kite.hpp" 32 | #include "../utils.hpp" 33 | 34 | namespace kiteconnect { 35 | inline std::vector kite::holdings() { 36 | return callApi, utils::json::JsonArray, true>( 37 | "portfolio.holdings", {}, {}, [](utils::json::JsonArray& data) { 38 | std::vector Holdings; 39 | for (auto& i : data) { Holdings.emplace_back(i.GetObject()); } 40 | return Holdings; 41 | }); 42 | }; 43 | 44 | inline positions kite::getPositions() { 45 | return callApi("portfolio.positions"); 46 | }; 47 | 48 | inline bool kite::convertPosition(const convertPositionParams& params) { 49 | utils::http::Params bodyParams = { 50 | { "exchange", params.exchange }, 51 | { "tradingsymbol", params.symbol }, 52 | { "transaction_type", params.transactionType }, 53 | { "position_type", params.positionType }, 54 | { "quantity", std::to_string(params.quantity) }, 55 | { "old_product", params.oldProduct }, 56 | { "new_product", params.newProduct }, 57 | }; 58 | return callApi("portfolio.positions.convert", bodyParams); 59 | }; 60 | }; // namespace kiteconnect -------------------------------------------------------------------------------- /examples/example1.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2021 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #include "kitepp.hpp" 27 | #include 28 | #include 29 | 30 | namespace kc = kiteconnect; 31 | 32 | int main() { 33 | try { 34 | kc::kite Kite(std::getenv("KITE_API_KEY")); 35 | std::string apiSecret = std::getenv("KITE_API_SECRET"); 36 | 37 | std::cout << "login URL: " << Kite.loginURL() << '\n'; 38 | std::cout << "login with this URL and obtain the request token\n"; 39 | 40 | std::string reqToken; 41 | std::cout << "enter obtained request token: "; 42 | std::cin >> reqToken; 43 | 44 | std::string accessToken = 45 | Kite.generateSession(reqToken, apiSecret).tokens.accessToken; 46 | Kite.setAccessToken(accessToken); 47 | std::cout << "access token is " << Kite.getAccessToken() << '\n'; 48 | 49 | kc::userProfile profile = Kite.profile(); 50 | std::cout << "name: " << profile.userName << "\n"; 51 | std::cout << "email: " << profile.email << "\n"; 52 | 53 | // clang-format off 54 | } catch (kc::kiteppException& e) { 55 | std::cerr << e.what() << ", " << e.code() << ", " << e.message() << '\n'; 56 | } catch (kc::libException& e) { 57 | std::cerr << e.what() << '\n'; 58 | } 59 | catch (std::exception& e) { 60 | std::cerr << e.what() << std::endl; 61 | }; 62 | // clang-format on 63 | 64 | return 0; 65 | }; 66 | -------------------------------------------------------------------------------- /examples/example3.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2021 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | 28 | #include "kitepp.hpp" 29 | 30 | namespace kc = kiteconnect; 31 | 32 | void onConnect(kc::ticker* ws) { 33 | std::cout << "connected.. Subscribing now..\n"; 34 | ws->setMode("full", { 408065, 2953217 }); 35 | }; 36 | 37 | void onTicks(kc::ticker* ws, const std::vector& ticks) { 38 | for (const auto& i : ticks) { 39 | std::cout << "instrument token: " << i.instrumentToken 40 | << " last price: " << i.lastPrice << "\n"; 41 | }; 42 | }; 43 | 44 | void onError(kc::ticker* ws, int code, const std::string& message) { 45 | std::cout << "Error! Code: " << code << " message: " << message << "\n"; 46 | }; 47 | 48 | void onConnectError(kc::ticker* ws) { std::cout << "Couldn't connect..\n"; }; 49 | 50 | void onClose(kc::ticker* ws, int code, const std::string& message) { 51 | std::cout << "Closed the connection.. code: " << code 52 | << " message: " << message << "\n"; 53 | }; 54 | 55 | int main(int argc, char const* argv[]) { 56 | kc::ticker Ticker(std::getenv("KITE_API_KEY"), 5, true, 5); 57 | 58 | Ticker.setAccessToken(std::getenv("KITE_ACCESS_TOKEN")); 59 | Ticker.onConnect = onConnect; 60 | Ticker.onTicks = onTicks; 61 | Ticker.onError = onError; 62 | Ticker.onConnectError = onConnectError; 63 | Ticker.onClose = onClose; 64 | 65 | Ticker.connect(); 66 | Ticker.run(); 67 | Ticker.stop(); 68 | 69 | return 0; 70 | }; 71 | -------------------------------------------------------------------------------- /include/kitepp/kite/api.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2022 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #pragma once 27 | #pragma clang diagnostic ignored "-Wundefined-inline" 28 | 29 | #include "PicoSHA2/picosha2.h" 30 | 31 | #include "../kite.hpp" 32 | #include "../utils.hpp" 33 | 34 | namespace kiteconnect { 35 | 36 | inline kite::kite(string apikey): key(std::move(apikey)), client(root.c_str()) { 37 | client.set_default_headers({ { "X-Kite-Version", version } }); 38 | }; 39 | 40 | inline void kite::setApiKey(const string& arg) { key = arg; }; 41 | 42 | inline string kite::getApiKey() const { return key; }; 43 | 44 | inline string kite::loginURL() const { 45 | return FMT(loginUrlFmt, "api_key"_a = key); 46 | }; 47 | 48 | inline void kite::setAccessToken(const string& arg) { 49 | token = arg; 50 | authorization = FMT("token {0}:{1}", key, token); 51 | }; 52 | 53 | inline string kite::getAccessToken() const { return token; }; 54 | 55 | inline userSession kite::generateSession( 56 | const string& requestToken, const string& apiSecret) { 57 | return callApi("api.token", 58 | { 59 | { "api_key", key }, 60 | { "request_token", requestToken }, 61 | { "checksum", 62 | picosha2::hash256_hex_string(key + requestToken + apiSecret) }, 63 | }); 64 | }; 65 | 66 | inline bool kite::invalidateSession() { 67 | utils::http::response res = 68 | sendReq(endpoints.at("api.token.invalidate"), {}, { key, token }); 69 | return static_cast(res); 70 | }; 71 | } // namespace kiteconnect 72 | -------------------------------------------------------------------------------- /tests/unit/utils.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2022 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | 30 | #include 31 | 32 | #include "./kitepp.hpp" 33 | 34 | namespace kiteconnect::test { 35 | 36 | using std::string; 37 | namespace kc = kiteconnect; 38 | namespace utils = kc::internal::utils; 39 | 40 | // NOLINTBEGIN(cert-err58-cpp) 41 | inline const string API_KEY = "Uz7Mdn29ZGya31a"; 42 | inline const string REQUEST_TOKEN = "qKLeSUycwFEvWGw"; 43 | inline const string API_SECRET = "kqykYBBhGEwPziq"; 44 | inline const string ACCESS_TOKEN = "rqykYBfhGEsPziq"; 45 | // NOLINTEND(cert-err58-cpp) 46 | 47 | class mockKite : public kc::kite { 48 | public: 49 | mockKite(): kite(kc::test::API_KEY) {}; 50 | MOCK_METHOD(utils::http::response, sendReq, 51 | (const utils::http::endpoint& endpoint, const utils::http::Params& body, 52 | const utils::FmtArgs& fmtArgs), 53 | (override)); 54 | }; 55 | 56 | inline string readFile(const string& path) { 57 | std::ifstream jsonFile(path); 58 | if (!jsonFile.good()) { 59 | string fileName; 60 | try { 61 | size_t lastOfSlash = path.find_last_of('/'); 62 | if (lastOfSlash == std::string::npos) { 63 | throw std::runtime_error(""); 64 | }; 65 | fileName = path.substr(lastOfSlash + 1, path.size() - 1); 66 | } catch (const std::exception& ex) { 67 | throw std::runtime_error("invalid test data file path"); 68 | } 69 | throw std::runtime_error(FMT("missing test data file ({0})", fileName)); 70 | } 71 | 72 | std::stringstream buffer; 73 | buffer << jsonFile.rdbuf(); 74 | return buffer.str(); 75 | } 76 | } // namespace kiteconnect::test -------------------------------------------------------------------------------- /docs/header.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | $projectname: $title 13 | 14 | 15 | $title 16 | 17 | 18 | 19 | 20 | $treeview 21 | $search 22 | $mathjax 23 | 24 | $extrastylesheet 25 | 26 | 29 | 30 | 31 | 32 |
33 | 34 | 35 | 36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 53 | 54 | 55 | 56 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 |
45 |
$projectname 46 |  $projectnumber 47 | 48 |
49 | 50 |
$projectbrief
51 | 52 |
57 |
$projectbrief
58 |
$searchbox
69 |
70 | 71 | -------------------------------------------------------------------------------- /examples/example4.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2021 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | 28 | #include "kitepp.hpp" 29 | 30 | namespace kc = kiteconnect; 31 | 32 | void onConnect(kc::ticker* ws) { 33 | std::cout << "connected.. subscribing now..\n"; 34 | ws->setMode("full", { 408065, 2953217 }); 35 | }; 36 | 37 | unsigned int tickCount = 0; 38 | void onTicks(kc::ticker* ws, const std::vector& ticks) { 39 | tickCount++; 40 | for (const auto& i : ticks) { 41 | std::cout << "instrument token: " << i.instrumentToken 42 | << " last price: " << i.lastPrice << "\n"; 43 | }; 44 | if (tickCount >= 100) { ws->stop(); }; 45 | }; 46 | 47 | void onOrderUpdate(kc::ticker* ws, const kc::postback& postback) { 48 | std::cout << "Order update: trading symbol: " << postback.tradingSymbol 49 | << " status: " << postback.status 50 | << " filled quantity: " << postback.filledQuantity << "\n"; 51 | }; 52 | 53 | void onMessage(kc::ticker* ws, const std::string& message) { 54 | std::cout << "Received message: " << message << "\n"; 55 | } 56 | 57 | void onError(kc::ticker* ws, int code, const std::string& message) { 58 | std::cout << "Error! Code: " << code << " message: " << message << "\n"; 59 | }; 60 | 61 | void onConnectError(kc::ticker* ws) { std::cout << "Couldn't connect..\n"; }; 62 | 63 | void onTryReconnect(kc::ticker* ws, unsigned int attemptCount) { 64 | std::cout << "Trying to reconnect.. Attempt " << attemptCount << "\n"; 65 | }; 66 | 67 | void onReconnectFail(kc::ticker* ws) { std::cout << "Failed to reconnect!\n"; }; 68 | 69 | void onClose(kc::ticker* ws, int code, const std::string& message) { 70 | std::cout << "Closed the connection.. code: " << code 71 | << " message: " << message << "\n"; 72 | }; 73 | 74 | int main(int argc, char const* argv[]) { 75 | kc::ticker Ticker(std::getenv("KITE_API_KEY"), 5, true, 5); 76 | 77 | Ticker.setAccessToken(std::getenv("KITE_ACCESS_TOKEN")); 78 | Ticker.onConnect = onConnect; 79 | Ticker.onTicks = onTicks; 80 | Ticker.onOrderUpdate = onOrderUpdate; 81 | Ticker.onMessage = onMessage; 82 | Ticker.onError = onError; 83 | Ticker.onConnectError = onConnectError; 84 | Ticker.onTryReconnect = onTryReconnect; 85 | Ticker.onReconnectFail = onReconnectFail; 86 | Ticker.onClose = onClose; 87 | 88 | Ticker.connect(); 89 | Ticker.run(); 90 | Ticker.stop(); 91 | 92 | return 0; 93 | }; 94 | -------------------------------------------------------------------------------- /include/kitepp/kite/internal.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2022 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include 30 | 31 | #include "kitepp/exceptions.hpp" 32 | #include "uri-parser/include/parser.hpp" 33 | 34 | #include "../kite.hpp" 35 | #include "../utils.hpp" 36 | 37 | namespace kiteconnect { 38 | 39 | inline string kite::getAuth() const { return authorization; } 40 | 41 | inline string kite::encodeSymbolsList(const std::vector& symbols) { 42 | string symbolsList; 43 | for (const auto& symbol : symbols) { 44 | size_t colonPos = symbol.find_first_of(':'); 45 | if (colonPos == std::string::npos) { 46 | throw libException("invalid symbol"); 47 | }; 48 | string exchange = symbol.substr(0, colonPos); 49 | string ticker = symbol.substr(colonPos + 1); 50 | 51 | symbolsList.append( 52 | FMT("i={0}:{1}&", exchange, parser::encodeUrl(ticker))); 53 | }; 54 | 55 | if (!symbolsList.empty()) { symbolsList.pop_back(); }; 56 | return symbolsList; 57 | } 58 | 59 | // GMock requires mock methods to be virtual (hi-perf dep injection is not 60 | // possible here ಥ﹏ಥ). Macro used to eliminate vptr overhead. 61 | inline utils::http::response kite::sendReq( 62 | const utils::http::endpoint& endpoint, const utils::http::Params& body, 63 | const utils::FmtArgs& fmtArgs) { 64 | if (endpoint.contentType == utils::http::CONTENT_TYPE::JSON) { 65 | return utils::http::request { endpoint.method, endpoint.Path(fmtArgs), 66 | getAuth(), body, endpoint.contentType, endpoint.responseType, 67 | body.begin()->second } 68 | .send(client); 69 | } 70 | return utils::http::request { endpoint.method, endpoint.Path(fmtArgs), 71 | getAuth(), body, endpoint.contentType, endpoint.responseType } 72 | .send(client); 73 | }; 74 | 75 | template 76 | inline Res kite::callApi(const string& service, const utils::http::Params& body, 77 | const utils::FmtArgs& fmtArgs, 78 | utils::json::CustomParser customParser) { 79 | utils::http::response res = sendReq(endpoints.at(service), body, fmtArgs); 80 | if (!res) { 81 | kiteconnect::internal::throwException( 82 | res.errorType, res.code, res.message); 83 | } 84 | return utils::json::parse( 85 | res.data, customParser); 86 | } 87 | } // namespace kiteconnect 88 | -------------------------------------------------------------------------------- /include/kitepp/userconstants.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2022 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #pragma once 27 | 28 | /** 29 | * @file userconstants.hpp 30 | * @brief Useful constants users can utilize. 31 | */ 32 | 33 | #include 34 | 35 | namespace kiteconnect { 36 | // NOLINTBEGIN(cert-err58-cpp) 37 | 38 | using std::string; 39 | 40 | // Products 41 | const string PRODUCT_MIS = "MIS"; 42 | const string PRODUCT_CNC = "CNC"; 43 | const string PRODUCT_NRML = "NRML"; 44 | const string PRODUCT_CO = "CO"; 45 | const string PRODUCT_BO = "BO"; 46 | 47 | // Order types 48 | const string ORDER_TYPE_MARKET = "MARKET"; 49 | const string ORDER_TYPE_LIMIT = "LIMIT"; 50 | const string ORDER_TYPE_SLM = "SL-M"; 51 | const string ORDER_TYPE_SL = "SL"; 52 | 53 | // Varities 54 | const string VARIETY_REGULAR = "regular"; 55 | const string VARIETY_BO = "bo"; 56 | const string VARIETY_CO = "co"; 57 | const string VARIETY_AMO = "amo"; 58 | const string VARIETY_ICEBERG = "iceberg"; 59 | 60 | // Transaction type 61 | const string TRANSACTION_TYPE_BUY = "BUY"; 62 | const string TRANSACTION_TYPE_SELL = "SELL"; 63 | 64 | // Validity 65 | const string VALIDITY_DAY = "DAY"; 66 | const string VALIDITY_IOC = "IOC"; 67 | const string VALIDITY_TTL = "TTL"; 68 | 69 | // Exchanges 70 | const string EXCHANGE_NSE = "NSE"; 71 | const string EXCHANGE_BSE = "BSE"; 72 | const string EXCHANGE_NFO = "NFO"; 73 | const string EXCHANGE_CDS = "CDS"; 74 | const string EXCHANGE_BFO = "BFO"; 75 | const string EXCHANGE_MCX = "MCX"; 76 | 77 | // Margins segments 78 | const string MARGIN_EQUITY = "equity"; 79 | const string MARGIN_COMMODITY = "commodity"; 80 | 81 | // Status constants 82 | const string STATUS_COMPLETE = "COMPLETE"; 83 | const string STATUS_REJECTED = "REJECTED"; 84 | const string STATUS_CANCELLED = "CANCELLED"; 85 | 86 | // GTT order type 87 | const string GTT_TYPE_OCO = "two-leg"; 88 | const string GTT_TYPE_SINGLE = "single"; 89 | 90 | // GTT order status 91 | const string GTT_STATUS_ACTIVE = "active"; 92 | const string GTT_STATUS_TRIGGERED = "triggered"; 93 | const string GTT_STATUS_DISABLED = "disabled"; 94 | const string GTT_STATUS_EXPIRED = "expired"; 95 | const string GTT_STATUS_CANCELLED = "cancelled"; 96 | const string GTT_STATUS_REJECTED = "rejected"; 97 | const string GTT_STATUS_DELETED = "deleted"; 98 | 99 | // kiteWS modes 100 | const string MODE_LTP = "ltp"; 101 | const string MODE_QUOTE = "quote"; 102 | const string MODE_FULL = "full"; 103 | 104 | // NOLINTEND(cert-err58-cpp) 105 | } // namespace kiteconnect 106 | -------------------------------------------------------------------------------- /include/kitepp/kite/margins.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2023 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #pragma once 27 | #pragma clang diagnostic ignored "-Wundefined-inline" 28 | 29 | #include 30 | 31 | #include "../kite.hpp" 32 | #include "../utils.hpp" 33 | 34 | namespace kiteconnect { 35 | inline std::vector kite::getOrderMargins( 36 | const std::vector& params) { 37 | utils::json::json ordersJson; 38 | ordersJson.array(params, [&](const marginsParams& param, 39 | rj::Value& buffer) { 40 | ordersJson.field("exchange", param.exchange, &buffer); 41 | ordersJson.field("tradingsymbol", param.tradingsymbol, &buffer); 42 | ordersJson.field("transaction_type", param.transactionType, &buffer); 43 | ordersJson.field("variety", param.variety, &buffer); 44 | ordersJson.field("product", param.product, &buffer); 45 | ordersJson.field("order_type", param.orderType, &buffer); 46 | ordersJson.field("quantity", param.quantity, &buffer); 47 | ordersJson.field("price", param.price, &buffer); 48 | ordersJson.field("trigger_price", param.triggerPrice, &buffer); 49 | }); 50 | 51 | return callApi, utils::json::JsonArray, true>( 52 | "margins.orders", { { "", ordersJson.serialize() } }, {}, 53 | [](utils::json::JsonArray& data) { 54 | std::vector margins; 55 | for (auto& i : data) { margins.emplace_back(i.GetObject()); } 56 | return margins; 57 | }); 58 | }; 59 | 60 | inline basketMargins kite::getBasketMargins( 61 | const std::vector& params, bool considerPositions) { 62 | utils::json::json ordersJson; 63 | ordersJson.array(params, [&](const marginsParams& param, 64 | rj::Value& buffer) { 65 | ordersJson.field("exchange", param.exchange, &buffer); 66 | ordersJson.field("tradingsymbol", param.tradingsymbol, &buffer); 67 | ordersJson.field("transaction_type", param.transactionType, &buffer); 68 | ordersJson.field("variety", param.variety, &buffer); 69 | ordersJson.field("product", param.product, &buffer); 70 | ordersJson.field("order_type", param.orderType, &buffer); 71 | ordersJson.field("quantity", param.quantity, &buffer); 72 | ordersJson.field("price", param.price, &buffer); 73 | ordersJson.field("trigger_price", param.triggerPrice, &buffer); 74 | }); 75 | 76 | return callApi("margins.basket", 77 | { { "", ordersJson.serialize() } }, 78 | { considerPositions ? "true" : "false" }); 79 | }; 80 | } // namespace kiteconnect -------------------------------------------------------------------------------- /include/kitepp/kite/market.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2022 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #pragma once 27 | #pragma clang diagnostic ignored "-Wundefined-inline" 28 | 29 | #include 30 | 31 | #include "../kite.hpp" 32 | #include "../utils.hpp" 33 | 34 | namespace kiteconnect { 35 | inline std::unordered_map kite::getQuote( 36 | const std::vector& symbols) { 37 | return callApi, utils::json::JsonObject, 38 | true>("market.quote", {}, { encodeSymbolsList(symbols) }, 39 | [](utils::json::JsonObject& data) { 40 | std::unordered_map Quotes; 41 | for (auto& i : data) { 42 | Quotes.emplace(i.name.GetString(), i.value.GetObject()); 43 | }; 44 | return Quotes; 45 | }); 46 | }; 47 | 48 | inline std::unordered_map kite::getOhlc( 49 | const std::vector& symbols) { 50 | return callApi, 51 | utils::json::JsonObject, true>("market.quote.ohlc", {}, 52 | { encodeSymbolsList(symbols) }, [](utils::json::JsonObject& data) { 53 | std::unordered_map Quotes; 54 | for (auto& i : data) { 55 | Quotes.emplace(i.name.GetString(), i.value.GetObject()); 56 | }; 57 | return Quotes; 58 | }); 59 | }; 60 | 61 | inline std::unordered_map kite::getLtp( 62 | const std::vector& symbols) { 63 | return callApi, 64 | utils::json::JsonObject, true>("market.quote.ltp", {}, 65 | { encodeSymbolsList(symbols) }, [](utils::json::JsonObject& data) { 66 | std::unordered_map Quotes; 67 | for (auto& i : data) { 68 | Quotes.emplace(i.name.GetString(), i.value.GetObject()); 69 | }; 70 | return Quotes; 71 | }); 72 | }; 73 | 74 | inline std::vector kite::getHistoricalData( 75 | const historicalDataParams& params) { 76 | static const auto toString = [](bool val) { return val ? "1" : "0"; }; 77 | return callApi, utils::json::JsonObject, true>( 78 | "market.historical", {}, 79 | { std::to_string(params.instrumentToken), params.interval, params.from, 80 | params.to, toString(params.continuous), toString(params.oi) }, 81 | [](utils::json::JsonObject& data) { 82 | std::vector candles; 83 | for (auto& i : data["candles"].GetArray()) { 84 | candles.emplace_back(i.GetArray()); 85 | } 86 | return candles; 87 | }); 88 | }; 89 | 90 | inline std::vector kite::getInstruments(const string& exchange) { 91 | utils::FmtArgs fmtArgs = {}; 92 | utils::http::endpoint endpoint; 93 | if (exchange.empty()) { 94 | endpoint = endpoints.at("market.instruments.all"); 95 | } else { 96 | endpoint = endpoints.at("market.instruments"); 97 | fmtArgs.emplace_back(exchange); 98 | } 99 | const auto response = sendReq(endpoint, {}, fmtArgs); 100 | if (!response) { return {}; }; 101 | 102 | return utils::parseInstruments(response.rawBody); 103 | }; 104 | 105 | }; // namespace kiteconnect -------------------------------------------------------------------------------- /include/kitepp/kite/gtt.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2022 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #pragma once 27 | #pragma clang diagnostic ignored "-Wundefined-inline" 28 | 29 | #include 30 | 31 | #include "../kite.hpp" 32 | #include "../utils.hpp" 33 | 34 | namespace kiteconnect { 35 | namespace internal { 36 | using std::string; 37 | 38 | template 39 | string getConditionJson(const T& params) { 40 | utils::json::json conditionJson; 41 | conditionJson.field("exchange", params.exchange); 42 | conditionJson.field("tradingsymbol", params.symbol); 43 | conditionJson.field("trigger_values", params.triggerValues); 44 | conditionJson.field("last_price", params.lastPrice); 45 | return conditionJson.serialize(); 46 | } 47 | 48 | template 49 | string getOrdersJson(const T& params) { 50 | utils::json::json ordersJson; 51 | ordersJson.array( 52 | params.gttParamsList, [&](const gttParams& param, rj::Value& buffer) { 53 | ordersJson.field("exchange", params.exchange, &buffer); 54 | ordersJson.field("tradingsymbol", params.symbol, &buffer); 55 | ordersJson.field( 56 | "transaction_type", param.transactionType, &buffer); 57 | ordersJson.field("quantity", param.quantity, &buffer); 58 | ordersJson.field("order_type", param.orderType, &buffer); 59 | ordersJson.field("product", param.product, &buffer); 60 | ordersJson.field("price", param.price, &buffer); 61 | }); 62 | return ordersJson.serialize(); 63 | } 64 | }; // namespace internal 65 | 66 | inline int kite::placeGtt(const placeGttParams& params) { 67 | utils::http::Params reqParams = { 68 | { "type", params.triggerType }, 69 | { "condition", internal::getConditionJson(params) }, 70 | { "orders", internal::getOrdersJson(params) }, 71 | }; 72 | 73 | return callApi( 74 | "gtt.place", reqParams, {}, [](utils::json::JsonObject& data) { 75 | return utils::json::get(data, "trigger_id"); 76 | }); 77 | }; 78 | 79 | inline std::vector kite::triggers() { 80 | return callApi, utils::json::JsonArray, true>( 81 | "gtt", {}, {}, [](utils::json::JsonArray& data) { 82 | std::vector Triggers; 83 | for (auto& i : data) { Triggers.emplace_back(i.GetObject()); } 84 | return Triggers; 85 | }); 86 | }; 87 | 88 | inline GTT kite::getGtt(int triggerId) { 89 | return callApi( 90 | "gtt.info", {}, { std::to_string(triggerId) }); 91 | }; 92 | 93 | inline int kite::modifyGtt(const kc::modifyGttParams& params) { 94 | utils::http::Params reqParams = { 95 | { "type", params.triggerType }, 96 | { "condition", internal::getConditionJson(params) }, 97 | { "orders", internal::getOrdersJson(params) }, 98 | }; 99 | 100 | return callApi("gtt.modify", reqParams, 101 | { std::to_string(params.triggerId) }, 102 | [](utils::json::JsonObject& data) { 103 | return utils::json::get(data, "trigger_id"); 104 | }); 105 | }; 106 | 107 | inline int kite::deleteGtt(int triggerId) { 108 | return callApi("gtt.delete", {}, 109 | { std::to_string(triggerId) }, [](utils::json::JsonObject& data) { 110 | return utils::json::get(data, "trigger_id"); 111 | }); 112 | }; 113 | 114 | } // namespace kiteconnect -------------------------------------------------------------------------------- /cmake/modules/FindGMock.cmake: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Locate the Google C++ Mocking Framework. 4 | # (This file is almost an identical copy of the original FindGTest.cmake file, 5 | # feel free to use it as it is or modify it for your own needs.) 6 | # 7 | # 8 | # Defines the following variables: 9 | # 10 | # GMOCK_FOUND - Found the Google Testing framework 11 | # GMOCK_INCLUDE_DIRS - Include directories 12 | # 13 | # Also defines the library variables below as normal 14 | # variables. These contain debug/optimized keywords when 15 | # a debugging library is found. 16 | # 17 | # GMOCK_BOTH_LIBRARIES - Both libgmock & libgmock-main 18 | # GMOCK_LIBRARIES - libgmock 19 | # GMOCK_MAIN_LIBRARIES - libgmock-main 20 | # 21 | # Accepts the following variables as input: 22 | # 23 | # GMOCK_ROOT - (as a CMake or environment variable) 24 | # The root directory of the gmock install prefix 25 | # 26 | # GMOCK_MSVC_SEARCH - If compiling with MSVC, this variable can be set to 27 | # "MD" or "MT" to enable searching a gmock build tree 28 | # (defaults: "MD") 29 | # 30 | #----------------------- 31 | # Example Usage: 32 | # 33 | # find_package(GMock REQUIRED) 34 | # include_directories(${GMOCK_INCLUDE_DIRS}) 35 | # 36 | # add_executable(foo foo.cc) 37 | # target_link_libraries(foo ${GMOCK_BOTH_LIBRARIES}) 38 | # 39 | #============================================================================= 40 | # This file is released under the MIT licence: 41 | # 42 | # Copyright (c) 2011 Matej Svec 43 | # 44 | # Permission is hereby granted, free of charge, to any person obtaining a copy 45 | # of this software and associated documentation files (the "Software"), to 46 | # deal in the Software without restriction, including without limitation the 47 | # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 48 | # sell copies of the Software, and to permit persons to whom the Software is 49 | # furnished to do so, subject to the following conditions: 50 | # 51 | # The above copyright notice and this permission notice shall be included in 52 | # all copies or substantial portions of the Software. 53 | # 54 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 55 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 56 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 57 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 58 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 59 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 60 | # IN THE SOFTWARE. 61 | #============================================================================= 62 | 63 | 64 | function(_gmock_append_debugs _endvar _library) 65 | if(${_library} AND ${_library}_DEBUG) 66 | set(_output optimized ${${_library}} debug ${${_library}_DEBUG}) 67 | else() 68 | set(_output ${${_library}}) 69 | endif() 70 | set(${_endvar} ${_output} PARENT_SCOPE) 71 | endfunction() 72 | 73 | function(_gmock_find_library _name) 74 | find_library(${_name} 75 | NAMES ${ARGN} 76 | HINTS 77 | $ENV{GMOCK_ROOT} 78 | ${GMOCK_ROOT} 79 | PATH_SUFFIXES ${_gmock_libpath_suffixes} 80 | ) 81 | mark_as_advanced(${_name}) 82 | endfunction() 83 | 84 | 85 | if(NOT DEFINED GMOCK_MSVC_SEARCH) 86 | set(GMOCK_MSVC_SEARCH MD) 87 | endif() 88 | 89 | set(_gmock_libpath_suffixes lib) 90 | if(MSVC) 91 | if(GMOCK_MSVC_SEARCH STREQUAL "MD") 92 | list(APPEND _gmock_libpath_suffixes 93 | msvc/gmock-md/Debug 94 | msvc/gmock-md/Release) 95 | elseif(GMOCK_MSVC_SEARCH STREQUAL "MT") 96 | list(APPEND _gmock_libpath_suffixes 97 | msvc/gmock/Debug 98 | msvc/gmock/Release) 99 | endif() 100 | endif() 101 | 102 | find_path(GMOCK_INCLUDE_DIR gmock/gmock.h 103 | HINTS 104 | $ENV{GMOCK_ROOT}/include 105 | ${GMOCK_ROOT}/include 106 | ) 107 | mark_as_advanced(GMOCK_INCLUDE_DIR) 108 | 109 | if(MSVC AND GMOCK_MSVC_SEARCH STREQUAL "MD") 110 | # The provided /MD project files for Google Mock add -md suffixes to the 111 | # library names. 112 | _gmock_find_library(GMOCK_LIBRARY gmock-md gmock) 113 | _gmock_find_library(GMOCK_LIBRARY_DEBUG gmock-mdd gmockd) 114 | _gmock_find_library(GMOCK_MAIN_LIBRARY gmock_main-md gmock_main) 115 | _gmock_find_library(GMOCK_MAIN_LIBRARY_DEBUG gmock_main-mdd gmock_maind) 116 | else() 117 | _gmock_find_library(GMOCK_LIBRARY gmock) 118 | _gmock_find_library(GMOCK_LIBRARY_DEBUG gmockd) 119 | _gmock_find_library(GMOCK_MAIN_LIBRARY gmock_main) 120 | _gmock_find_library(GMOCK_MAIN_LIBRARY_DEBUG gmock_maind) 121 | endif() 122 | 123 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(GMock DEFAULT_MSG GMOCK_LIBRARY GMOCK_INCLUDE_DIR GMOCK_MAIN_LIBRARY) 124 | 125 | if(GMOCK_FOUND) 126 | set(GMOCK_INCLUDE_DIRS ${GMOCK_INCLUDE_DIR}) 127 | _gmock_append_debugs(GMOCK_LIBRARIES GMOCK_LIBRARY) 128 | _gmock_append_debugs(GMOCK_MAIN_LIBRARIES GMOCK_MAIN_LIBRARY) 129 | set(GMOCK_BOTH_LIBRARIES ${GMOCK_LIBRARIES} ${GMOCK_MAIN_LIBRARIES}) 130 | endif() 131 | 132 | -------------------------------------------------------------------------------- /include/kitepp/responses/ws.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2022 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include 30 | 31 | #include "../utils.hpp" 32 | #include "rapidjson/include/rapidjson/document.h" 33 | #include "rapidjson/include/rapidjson/rapidjson.h" 34 | 35 | namespace kiteconnect { 36 | 37 | using std::string; 38 | namespace kc = kiteconnect; 39 | namespace rj = rapidjson; 40 | namespace utils = kc::internal::utils; 41 | 42 | /// Represents a single entry in market depth returned by `ticker`. 43 | struct depthWS { 44 | int16_t orders = -1; 45 | int32_t quantity = -1; 46 | double price = -1; 47 | }; 48 | 49 | /// Represents a single market data tick. 50 | struct tick { 51 | int32_t instrumentToken = -1; 52 | int32_t timestamp = -1; 53 | int32_t lastTradeTime = -1; 54 | int32_t lastTradedQuantity = -1; 55 | int32_t totalBuyQuantity = -1; 56 | int32_t totalSellQuantity = -1; 57 | int32_t volumeTraded = -1; 58 | int32_t oi = -1; 59 | int32_t oiDayHigh = -1; 60 | int32_t oiDayLow = -1; 61 | string mode; 62 | double lastPrice = -1; 63 | double averageTradePrice = -1; 64 | double netChange = -1; 65 | bool isTradable; 66 | struct OHLC { 67 | double open = -1; 68 | double high = -1; 69 | double low = -1; 70 | double close = -1; 71 | } ohlc; 72 | struct m_depth { 73 | std::vector buy; 74 | std::vector sell; 75 | } marketDepth; 76 | }; 77 | 78 | /// Represents a postback. 79 | struct postback { 80 | postback() = default; 81 | explicit postback(const rj::Value::Object& val) { parse(val); }; 82 | 83 | void parse(const rj::Value::Object& val) { 84 | orderId = utils::json::get(val, "order_id"); 85 | exchangeOrderId = utils::json::get(val, "exchange_order_id"); 86 | placedBy = utils::json::get(val, "placed_by"); 87 | status = utils::json::get(val, "status"); 88 | statusMessage = utils::json::get(val, "status_message"); 89 | tradingSymbol = utils::json::get(val, "tradingsymbol"); 90 | exchange = utils::json::get(val, "exchange"); 91 | orderType = utils::json::get(val, "order_type"); 92 | transactionType = utils::json::get(val, "transaction_type"); 93 | validity = utils::json::get(val, "validity"); 94 | product = utils::json::get(val, "product"); 95 | averagePrice = utils::json::get(val, "average_price"); 96 | price = utils::json::get(val, "price"); 97 | quantity = utils::json::get(val, "quantity"); 98 | filledQuantity = utils::json::get(val, "filled_quantity"); 99 | unfilledQuantity = utils::json::get(val, "unfilled_quantity"); 100 | triggerPrice = utils::json::get(val, "trigger_price"); 101 | userId = utils::json::get(val, "user_id"); 102 | orderTimestamp = utils::json::get(val, "order_timestamp"); 103 | exchangeTimestamp = utils::json::get(val, "exchange_timestamp"); 104 | checksum = utils::json::get(val, "checksum"); 105 | }; 106 | 107 | int quantity = -1; 108 | int filledQuantity = -1; 109 | int unfilledQuantity = -1; 110 | double averagePrice = -1; 111 | double price = -1; 112 | double triggerPrice = -1; 113 | string orderId; 114 | string exchangeOrderId; 115 | string placedBy; 116 | string status; 117 | string statusMessage; 118 | string tradingSymbol; 119 | string exchange; 120 | string orderType; 121 | string transactionType; 122 | string validity; 123 | string product; 124 | string userId; 125 | string orderTimestamp; 126 | string exchangeTimestamp; 127 | string checksum; 128 | }; 129 | 130 | } // namespace kiteconnect -------------------------------------------------------------------------------- /tests/unit/kite/api.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2022 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include "../kitepp.hpp" 37 | #include "../utils.hpp" 38 | 39 | using std::string; 40 | using ::testing::ByMove; 41 | using ::testing::Return; 42 | using ::testing::StrictMock; 43 | namespace kc = kiteconnect; 44 | namespace utils = kc::internal::utils; 45 | 46 | TEST(kiteTest, constructorTest) { 47 | StrictMock Kite; 48 | const string API_KEY = "Uz7Mdn29ZGya31a"; 49 | 50 | EXPECT_EQ(Kite.getApiKey(), API_KEY); 51 | }; 52 | 53 | TEST(kiteTest, loginURLTest) { 54 | StrictMock Kite; 55 | const string LOGIN_URL = 56 | "https://kite.zerodha.com/connect/login?v=3&api_key=Uz7Mdn29ZGya31a"; 57 | 58 | EXPECT_EQ(Kite.loginURL(), LOGIN_URL); 59 | }; 60 | 61 | TEST(kiteTest, generateSessionTest) { 62 | const string JSON = 63 | kc::test::readFile("../tests/mock_custom/generate_session.json"); 64 | StrictMock Kite; 65 | EXPECT_CALL(Kite, sendReq(utils::http::endpoint { utils::http::METHOD::POST, 66 | "/session/token" }, 67 | utils::http::Params { 68 | { "api_key", "Uz7Mdn29ZGya31a" }, 69 | { "request_token", "qKLeSUycwFEvWGw" }, 70 | { "checksum", "ac90aa6cafb2bab90a172d38f70c66cbc1" 71 | "d96601852123530459fcabbc487d4f" }, 72 | }, 73 | utils::FmtArgs {})) 74 | .Times(1) 75 | .WillOnce( 76 | Return(ByMove(utils::http::response(utils::http::code::OK, JSON)))); 77 | 78 | kc::userSession session = 79 | Kite.generateSession(kc::test::REQUEST_TOKEN, kc::test::API_SECRET); 80 | 81 | // Expected values 82 | EXPECT_EQ(session.profile.userID, "XX000"); 83 | EXPECT_EQ(session.profile.userName, "Kite Connect"); 84 | EXPECT_EQ(session.profile.userShortName, "Kite"); 85 | EXPECT_EQ(session.profile.avatarURL, ""); 86 | EXPECT_EQ(session.profile.userType, "investor"); 87 | EXPECT_EQ(session.profile.email, "kite@kite.trade"); 88 | EXPECT_EQ(session.profile.broker, "ZERODHA"); 89 | EXPECT_THAT(session.profile.products, 90 | ::testing::ElementsAre("BO", "CNC", "CO", "MIS", "NRML")); 91 | EXPECT_THAT(session.profile.orderTypes, 92 | ::testing::ElementsAre("LIMIT", "MARKET", "SL", "SL-M")); 93 | EXPECT_THAT(session.profile.exchanges, 94 | ::testing::ElementsAre("MCX", "BSE", "NSE", "BFO", "NFO", "CDS")); 95 | 96 | EXPECT_EQ(session.tokens.userID, "XX000"); 97 | EXPECT_EQ(session.tokens.accessToken, "yyyyyy"); 98 | EXPECT_EQ(session.tokens.refreshToken, ""); 99 | 100 | EXPECT_EQ(session.apiKey, "xxxxxx"); 101 | EXPECT_EQ(session.publicToken, "zzzzzz"); 102 | EXPECT_EQ(session.loginTime, "2018-01-01 16:15:14"); 103 | }; 104 | 105 | TEST(kiteTest, invalidateSessionTest) { 106 | const string JSON = 107 | kc::test::readFile("../tests/mock_custom/invalidate_session.json"); 108 | StrictMock Kite; 109 | Kite.setAccessToken(kc::test::ACCESS_TOKEN); 110 | 111 | EXPECT_CALL( 112 | Kite, sendReq(utils::http::endpoint { utils::http::METHOD::DEL, 113 | "/session/token?api_key={0}&access_token={1}" }, 114 | utils::http::Params {}, 115 | utils::FmtArgs { kc::test::API_KEY, kc::test::ACCESS_TOKEN })) 116 | .Times(1) 117 | .WillOnce( 118 | Return(ByMove(utils::http::response(utils::http::code::OK, JSON)))); 119 | 120 | const bool RESULT = Kite.invalidateSession(); 121 | EXPECT_EQ(RESULT, true); 122 | }; 123 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(CppKiteConnect) 3 | 4 | # set variables 5 | set(CMAKE_CXX_STANDARD 17) 6 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 7 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/modules/") 8 | 9 | # detect Linux (for optional linking of libuv) 10 | if(UNIX AND NOT APPLE) 11 | message(STATUS "environment set to linux") 12 | set(LINUX TRUE) 13 | endif() 14 | 15 | # set project include directory 16 | include_directories("${CMAKE_SOURCE_DIR}/include") 17 | 18 | # find deps 19 | set(LINUX_AND_UV_NOT_FOUND false) 20 | 21 | if(BUILD_EXAMPLES OR BUILD_TESTS) 22 | find_package(Threads REQUIRED) 23 | find_package(OpenSSL REQUIRED) 24 | find_package(ZLIB REQUIRED) 25 | find_library(UWS_LIB uWS REQUIRED) 26 | find_path(UWS_INCLUDE uWS REQUIRED) 27 | 28 | if(DEFINED LINUX) 29 | find_library(UV_LIB uv) 30 | find_path(UV_INCLUDE "uv.h") 31 | else() 32 | find_library(UV_LIB uv REQUIRED) 33 | find_path(UV_INCLUDE "uv.h" REQUIRED) 34 | endif() 35 | 36 | if(BUILD_TESTS) 37 | find_package(GTest REQUIRED) 38 | find_package(GMock REQUIRED) 39 | endif() 40 | 41 | if((NOT UV_LIB OR NOT UV_INCLUDE) AND DEFINED LINUX) 42 | set(LINUX_AND_UV_NOT_FOUND true) 43 | message(STATUS "couldn't find libuv") 44 | endif() 45 | endif() 46 | 47 | # build examples 48 | if(BUILD_EXAMPLES) 49 | function(build_exmaple example_name) 50 | add_executable(${example_name} "${CMAKE_SOURCE_DIR}/examples/${example_name}.cpp") 51 | 52 | if(LINUX_AND_UV_NOT_FOUND) 53 | target_include_directories(${example_name} PUBLIC ${UWS_INCLUDE}) 54 | target_link_libraries(${example_name} PUBLIC Threads::Threads OpenSSL::SSL OpenSSL::Crypto ZLIB::ZLIB ${UWS_LIB}) 55 | else() 56 | target_include_directories(${example_name} PUBLIC ${UWS_INCLUDE} ${UV_INCLUDE}) 57 | target_link_libraries(${example_name} PUBLIC Threads::Threads OpenSSL::SSL OpenSSL::Crypto ZLIB::ZLIB ${UWS_LIB} ${UV_LIB}) 58 | endif() 59 | endfunction(build_exmaple) 60 | 61 | build_exmaple(example1) 62 | build_exmaple(example2) 63 | build_exmaple(example3) 64 | build_exmaple(example4) 65 | endif() 66 | 67 | # build tests 68 | if(BUILD_TESTS) 69 | include(CTest) 70 | option(CMAKE_USE_WIN32_THREADS_INIT "using WIN32 threads" ON) 71 | option(gtest_disable_pthreads "disabling pthreads in gtest" ON) 72 | 73 | # kite-test 74 | set(KITE_TEST_BINARY_NAME kiteTest) 75 | file(GLOB test_files 76 | "${CMAKE_SOURCE_DIR}/tests/unit/kite/*.cpp" 77 | ) 78 | add_executable(${KITE_TEST_BINARY_NAME} ${test_files}) 79 | target_include_directories(${KITE_TEST_BINARY_NAME} PUBLIC ${GTEST_INCLUDE_DIRS} ${GMOCK_INCLUDE_DIRS}) 80 | target_link_libraries(${KITE_TEST_BINARY_NAME} PUBLIC OpenSSL::SSL OpenSSL::Crypto ${GTEST_BOTH_LIBRARIES} ${GMOCK_BOTH_LIBRARIES} Threads::Threads) 81 | add_test(NAME kite-test COMMAND ${KITE_TEST_BINARY_NAME}) 82 | 83 | # ticker-test 84 | set(TICKER_TEST_BINARY_NAME tickerTest) 85 | add_executable(${TICKER_TEST_BINARY_NAME} "${CMAKE_SOURCE_DIR}/tests/unit/tickertest.cpp") 86 | 87 | if(LINUX_AND_UV_NOT_FOUND) 88 | target_include_directories(${TICKER_TEST_BINARY_NAME} PUBLIC ${UWS_INCLUDE} ${GTEST_INCLUDE_DIRS}) 89 | target_link_libraries(${TICKER_TEST_BINARY_NAME} PUBLIC OpenSSL::SSL OpenSSL::Crypto ZLIB::ZLIB ${UWS_LIB} ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES} Threads::Threads) 90 | else() 91 | target_include_directories(${TICKER_TEST_BINARY_NAME} PUBLIC ${UV_INCLUDE} ${UWS_INCLUDE} ${GTEST_INCLUDE_DIRS}) 92 | target_link_libraries(${TICKER_TEST_BINARY_NAME} PUBLIC OpenSSL::SSL OpenSSL::Crypto ZLIB::ZLIB ${UV_LIB} ${UWS_LIB} ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES} Threads::Threads) 93 | endif() 94 | 95 | add_test(NAME ticker-test COMMAND ${TICKER_TEST_BINARY_NAME}) 96 | endif() 97 | 98 | # generate docs 99 | if(BUILD_DOCS) 100 | find_package(Doxygen) 101 | 102 | if(DOXYGEN_FOUND) 103 | # set io files and configure doxyfile 104 | set(DOXY_FILE Doxyfile.in) 105 | set(DOXYGEN_IN ${CMAKE_SOURCE_DIR}/cmake/templates/${DOXY_FILE}) 106 | set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile.out) 107 | configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY) 108 | 109 | # ! don't add to the `all` target. doing so will build build docs everytime. 110 | add_custom_target(docs 111 | COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT} 112 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 113 | COMMENT "generating documentation with doxygen" 114 | VERBATIM) 115 | else(DOXYGEN_FOUND) 116 | message(FATAL_ERROR "doxygen is required for generating documentation") 117 | endif(DOXYGEN_FOUND) 118 | endif() -------------------------------------------------------------------------------- /include/kitepp/kite/mf.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2022 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #pragma once 27 | #pragma clang diagnostic ignored "-Wundefined-inline" 28 | 29 | #include 30 | 31 | #include "../kite.hpp" 32 | #include "../utils.hpp" 33 | 34 | namespace kiteconnect { 35 | inline string kite::placeMfOrder(const placeMfOrderParams& params) { 36 | // required parameters 37 | utils::http::Params bodyParams = { 38 | { "tradingsymbol", params.symbol }, 39 | { "transaction_type", params.transactionType }, 40 | }; 41 | // optional parameters 42 | utils::addParam(bodyParams, params.quantity, "quantity"); 43 | utils::addParam(bodyParams, params.amount, "amount"); 44 | utils::addParam(bodyParams, params.tag, "tag"); 45 | 46 | return callApi( 47 | "mf.order.place", bodyParams, {}, [](utils::json::JsonObject& data) { 48 | return utils::json::get(data, "order_id"); 49 | }); 50 | }; 51 | 52 | inline string kite::cancelMfOrder(const string& orderId) { 53 | return callApi( 54 | "mf.order.cancel", {}, { orderId }, [](utils::json::JsonObject& data) { 55 | return utils::json::get(data, "order_id"); 56 | }); 57 | }; 58 | 59 | inline std::vector kite::getMfOrders() { 60 | return callApi, utils::json::JsonArray, true>( 61 | "mf.orders", {}, {}, [](utils::json::JsonArray& data) { 62 | std::vector Orders; 63 | for (auto& i : data) { Orders.emplace_back(i.GetObject()); } 64 | return Orders; 65 | }); 66 | }; 67 | 68 | inline mfOrder kite::getMfOrder(const string& orderId) { 69 | return callApi( 70 | "mf.order.info", {}, { orderId }); 71 | }; 72 | 73 | inline std::vector kite::getMfHoldings() { 74 | return callApi, utils::json::JsonArray, true>( 75 | "mf.holdings", {}, {}, [](utils::json::JsonArray& data) { 76 | std::vector holdings; 77 | for (auto& i : data) { holdings.emplace_back(i.GetObject()); } 78 | return holdings; 79 | }); 80 | }; 81 | 82 | inline placeMfSipResponse kite::placeMfSip(const placeMfSipParams& params) { 83 | // required parameters 84 | utils::http::Params bodyParams = { 85 | { "tradingsymbol", params.symbol }, 86 | { "amount", std::to_string(params.amount) }, 87 | { "instalments", std::to_string(params.installments) }, 88 | { "frequency", params.frequency }, 89 | }; 90 | // optional parameters 91 | utils::addParam(bodyParams, params.initialAmount, "initial_amount"); 92 | utils::addParam(bodyParams, params.installmentDay, "instalment_day"); 93 | utils::addParam(bodyParams, params.tag, "tag"); 94 | 95 | return callApi( 96 | "mf.sip.place", bodyParams); 97 | }; 98 | 99 | inline string kite::modifyMfSip(const modifyMfSipParams& params) { 100 | utils::http::Params bodyParams = {}; 101 | // optional parameters 102 | utils::addParam(bodyParams, params.amount, "amount"); 103 | utils::addParam(bodyParams, params.status, "status"); 104 | utils::addParam(bodyParams, params.installments, "instalments"); 105 | utils::addParam(bodyParams, params.frequency, "frequency"); 106 | utils::addParam(bodyParams, params.installmentDay, "instalment_day"); 107 | 108 | return callApi("mf.sip.modify", 109 | bodyParams, { params.sipId }, [](utils::json::JsonObject& data) { 110 | return utils::json::get(data, "order_id"); 111 | }); 112 | }; 113 | 114 | inline string kite::cancelMfSip(const string& sipId) { 115 | return callApi( 116 | "mf.sip.cancel", {}, { sipId }, [](utils::json::JsonObject& data) { 117 | return utils::json::get(data, "sip_id"); 118 | }); 119 | }; 120 | 121 | inline std::vector kite::getSips() { 122 | return callApi, utils::json::JsonArray, true>( 123 | "mf.sips", {}, {}, [](utils::json::JsonArray& data) { 124 | std::vector sips; 125 | for (auto& i : data) { sips.emplace_back(i.GetObject()); } 126 | return sips; 127 | }); 128 | }; 129 | 130 | inline mfSip kite::getSip(const string& sipId) { 131 | return callApi( 132 | "mf.sip.info", {}, { sipId }); 133 | }; 134 | 135 | inline std::vector kite::getMfInstruments() { 136 | const auto response = sendReq(endpoints.at("mf.instruments"), {}, {}); 137 | if (!response) { return {}; }; 138 | 139 | return utils::parseInstruments(response.rawBody); 140 | }; 141 | 142 | } // namespace kiteconnect -------------------------------------------------------------------------------- /include/kitepp/kite/order.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2022 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #pragma once 27 | #pragma clang diagnostic ignored "-Wundefined-inline" 28 | 29 | #include 30 | 31 | #include "../kite.hpp" 32 | #include "../utils.hpp" 33 | 34 | namespace kiteconnect { 35 | inline string kite::placeOrder(const placeOrderParams& params) { 36 | // required parameters 37 | utils::http::Params bodyParams = { 38 | { "exchange", params.exchange }, 39 | { "tradingsymbol", params.symbol }, 40 | { "transaction_type", params.transactionType }, 41 | { "quantity", std::to_string(params.quantity) }, 42 | { "product", params.product }, 43 | { "order_type", params.orderType }, 44 | }; 45 | // optional parameters 46 | utils::addParam(bodyParams, params.price, "price"); 47 | utils::addParam(bodyParams, params.validity, "validity"); 48 | utils::addParam(bodyParams, params.disclosedQuantity, "disclosed_quantity"); 49 | utils::addParam(bodyParams, params.triggerPrice, "trigger_price"); 50 | utils::addParam(bodyParams, params.squareOff, "squareoff"); 51 | utils::addParam(bodyParams, params.stopLoss, "stoploss"); 52 | utils::addParam(bodyParams, params.trailingStopLoss, "trailing_stoploss"); 53 | utils::addParam(bodyParams, params.icebergLegs, "iceberg_legs"); 54 | utils::addParam(bodyParams, params.icebergQuantity, "iceberg_quantity"); 55 | utils::addParam(bodyParams, params.validityTtl, "validity_ttl"); 56 | utils::addParam(bodyParams, params.tag, "tag"); 57 | 58 | return callApi("order.place", 59 | bodyParams, { params.variety }, [](utils::json::JsonObject& data) { 60 | return utils::json::get(data, "order_id"); 61 | }); 62 | }; 63 | 64 | inline string kite::modifyOrder(const modifyOrderParams& params) { 65 | utils::http::Params bodyParams = {}; 66 | // optional parameters 67 | utils::addParam(bodyParams, params.parentOrderId, "parent_order_id"); 68 | utils::addParam(bodyParams, params.quantity, "quantity"); 69 | utils::addParam(bodyParams, params.price, "price"); 70 | utils::addParam(bodyParams, params.orderType, "order_type"); 71 | utils::addParam(bodyParams, params.triggerPrice, "trigger_price"); 72 | utils::addParam(bodyParams, params.validity, "validity"); 73 | utils::addParam(bodyParams, params.disclosedQuantity, "disclosed_quantity"); 74 | 75 | return callApi("order.modify", 76 | bodyParams, { params.variety, params.orderId }, 77 | [](utils::json::JsonObject& data) { 78 | return utils::json::get(data, "order_id"); 79 | }); 80 | }; 81 | 82 | inline string kite::cancelOrder( 83 | const string& variety, const string& orderId, const string& parentOrderID) { 84 | string endpoint; 85 | utils::FmtArgs fmtArgs; 86 | if (variety == "bo") { 87 | endpoint = "order.cancel.bo"; 88 | fmtArgs = { variety, orderId, parentOrderID }; 89 | } else { 90 | endpoint = "order.cancel"; 91 | fmtArgs = { variety, orderId }; 92 | }; 93 | return callApi( 94 | endpoint, {}, fmtArgs, [](utils::json::JsonObject& data) { 95 | return utils::json::get(data, "order_id"); 96 | }); 97 | }; 98 | 99 | inline std::vector kite::orders() { 100 | return callApi, utils::json::JsonArray, true>( 101 | "orders", {}, {}, [](utils::json::JsonArray& data) { 102 | std::vector Orders; 103 | for (auto& i : data) { Orders.emplace_back(i.GetObject()); } 104 | return Orders; 105 | }); 106 | }; 107 | 108 | inline std::vector kite::orderHistory(const string& orderId) { 109 | return callApi, utils::json::JsonArray, true>( 110 | "order.info", {}, { orderId }, [](utils::json::JsonArray& data) { 111 | std::vector history; 112 | for (auto& i : data) { history.emplace_back(i.GetObject()); } 113 | return history; 114 | }); 115 | }; 116 | 117 | inline std::vector kite::trades() { 118 | return callApi, utils::json::JsonArray, true>( 119 | "trades", {}, {}, [](utils::json::JsonArray& data) { 120 | std::vector trades; 121 | for (auto& i : data) { trades.emplace_back(i.GetObject()); } 122 | return trades; 123 | }); 124 | }; 125 | 126 | inline std::vector kite::orderTrades(const string& orderId) { 127 | return callApi, utils::json::JsonArray, true>( 128 | "order.trades", {}, { orderId }, [](utils::json::JsonArray& data) { 129 | std::vector trades; 130 | for (auto& i : data) { trades.emplace_back(i.GetObject()); } 131 | return trades; 132 | }); 133 | }; 134 | } // namespace kiteconnect -------------------------------------------------------------------------------- /docs/mainpage.md: -------------------------------------------------------------------------------- 1 | # CPPKiteConnect Documentation 2 | 3 | [TOC] 4 | 5 | ## Overview 6 | 7 | The official C++ client for communicating with [Kite Connect API](https://kite.trade/). 8 | 9 | CPPKiteConnect is a header-only library that wraps around Zerodha's KiteConnect REST API and WebSockets API. It saves you the hassle of directly communicating with the APIs and provides an easy to use, native and modern C++ interface. 10 | 11 | ## Dependencies 12 | 13 | CPPKiteConnect requires C++17 and following dependancies: 14 | 15 | - [OpenSSL (devel)](https://github.com/openssl/openssl "OpenSSL") 16 | - [uWebSockets v0.14 (devel)](https://github.com/uNetworking/uWebSockets/tree/v0.14) and [its dependancies](https://github.com/hoytech/uWebSockets/blob/master/docs/Misc.-details.md#dependencies). 17 | - [googletest](https://github.com/google/googletest) and [googlemock](https://github.com/google/googletest) are required for running tests. 18 | - Doxygen is required for generating documentation. 19 | 20 | ## Getting dependencies 21 | 22 | ### Linux 23 | 24 | - On Fedora 32: 25 | `sudo dnf install openssl-devel zlib-devel` + (uWS v0.14) + (`gtest-devel gmock-devel` for running tests) 26 | - On Ubuntu: 27 | `sudo apt install libssl-dev zlib1g-dev` + (uWS v0.14) + (googletest, googlemock for running tests) 28 | 29 | ### Others & uWS v0.14 30 | 31 | Use package managers provided by your OS. Unless your package manager provides `v0.14` of `uWS`, you'll have to build and install it manually. 32 | 33 | You can also download source of the required dependencies by running `cmake .` in `deps` directory. This will place files in the same directory. 34 | 35 | ## Building & Installation 36 | 37 | Clone the repository and fetch the submodules 38 | 39 | ```sh 40 | git clone https://github.com/zerodha/cppkiteconnect.git 41 | submodule update --init --recursive 42 | ``` 43 | 44 | CPPKiteConnect is a header-only library. Copy the `include` folder to system or project's include path. 45 | 46 | ### Build 47 | 48 | ```bash 49 | mkdir build && cd build 50 | cmake .. -DBUILD_TESTS=On 51 | make 52 | ``` 53 | 54 | If `cmake` cannot find your `uWS` library, try providing it manually to `cmake` like `cmake .. -DUWS_LIB=/path/to/uWS.so`. Note that this will build the library but some tests might not be run. 55 | 56 | #### Build options 57 | 58 | | Option | Description 59 | | :-------------- | ---------: 60 | | `BUILD_TESTS` | Build tests 61 | | `BUILD_EXAMPLES` | Build examples | 62 | | `BUILD_DOCS` | Build docs 63 | 64 | ### Run tests 65 | 66 | ``make && make test ARGS='-V'`` 67 | 68 | ### Generate docs 69 | 70 | `make docs` 71 | 72 | ## Examples 73 | 74 | ### REST API 75 | 76 | ```{.cpp} 77 | #include 78 | #include 79 | #include "kitepp.hpp" 80 | 81 | namespace kc = kiteconnect; 82 | 83 | int main() { 84 | try { 85 | kc::kite Kite(std::getenv("KITE_API_KEY")); 86 | std::string apiSecret = std::getenv("KITE_API_SECRET"); 87 | 88 | std::cout << "login URL: " << Kite.loginURL() << '\n'; 89 | std::cout << "login with this URL and obtain the request token\n"; 90 | 91 | std::string reqToken; 92 | std::cout << "enter obtained request token: "; 93 | std::cin >> reqToken; 94 | 95 | std::string accessToken = 96 | Kite.generateSession(reqToken, apiSecret).tokens.accessToken; 97 | Kite.setAccessToken(accessToken); 98 | std::cout << "access token is " << Kite.getAccessToken() << '\n'; 99 | 100 | kc::userProfile profile = Kite.profile(); 101 | std::cout << "name: " << profile.userName << "\n"; 102 | std::cout << "email: " << profile.email << "\n"; 103 | 104 | } catch (kc::kiteppException& e) { 105 | std::cerr << e.what() << ", " << e.code() << ", " << e.message() << '\n'; 106 | } catch (kc::libException& e) { 107 | std::cerr << e.what() << '\n'; 108 | } 109 | catch (std::exception& e) { 110 | std::cerr << e.what() << std::endl; 111 | }; 112 | return 0; 113 | }; 114 | ``` 115 | 116 | ### Ticker 117 | 118 | ```{.cpp} 119 | #include 120 | #include "kitepp.hpp" 121 | 122 | namespace kc = kiteconnect; 123 | 124 | void onConnect(kc::ticker* ws) { 125 | std::cout << "Connected.. Subscribing now..\n"; 126 | ws->setMode("full", { 408065, 2953217 }); 127 | }; 128 | 129 | void onTicks(kc::ticker* ws, const std::vector& ticks) { 130 | for (const auto& i : ticks) { 131 | std::cout << "instrument token: " << i.instrumentToken 132 | << " last price: " << i.lastPrice << "\n"; 133 | }; 134 | }; 135 | 136 | void onError(kc::ticker* ws, int code, const std::string& message) { 137 | std::cout << "Error! Code: " << code << " message: " << message << "\n"; 138 | }; 139 | 140 | void onConnectError(kc::ticker* ws) { std::cout << "Couldn't connect..\n"; }; 141 | 142 | void onClose(kc::ticker* ws, int code, const std::string& message) { 143 | std::cout << "Closed the connection.. code: " << code 144 | << " message: " << message << "\n"; 145 | }; 146 | 147 | int main(int argc, char const* argv[]) { 148 | kc::ticker Ticker(std::getenv("KITE_API_KEY"), 5, true, 5); 149 | 150 | Ticker.setAccessToken(std::getenv("KITE_ACCESS_TOKEN")); 151 | Ticker.onConnect = onConnect; 152 | Ticker.onTicks = onTicks; 153 | Ticker.onError = onError; 154 | Ticker.onConnectError = onConnectError; 155 | Ticker.onClose = onClose; 156 | 157 | Ticker.connect(); 158 | Ticker.run(); 159 | Ticker.stop(); 160 | 161 | return 0; 162 | }; 163 | ``` 164 | 165 | More examples can be found in the [examples directory](https://github.com/zerodha/cppkiteconnect/tree/main/examples). 166 | 167 | ## Documentation {#documentation} 168 | 169 | - [KiteConnect API documentation](https://kite.trade/docs/connect/v3/) 170 | - [CPPKiteConnect reference documentation](https://kite.trade/docs/cppkiteconnect/) 171 | - [Hierarchial list of classes](hierarchy.html) 172 | - [`kite` (REST interface) class](classkiteconnect_1_1kite.html) 173 | - [`ticker` (WebSocket interface) class](classkiteconnect_1_1ticker.html) 174 | - [Useful user constants](userconstants_8hpp.html) 175 | - [Exceptions](classkiteconnect_1_1kiteppException.html) 176 | 177 | ## License 178 | 179 | [MIT](https://opensource.org/licenses/MIT) 180 | -------------------------------------------------------------------------------- /include/kitepp/responses/gtt.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2022 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | 30 | #include "../utils.hpp" 31 | #include "order.hpp" 32 | #include "rapidjson/include/rapidjson/document.h" 33 | #include "rapidjson/include/rapidjson/rapidjson.h" 34 | 35 | namespace kiteconnect { 36 | 37 | using std::string; 38 | namespace rj = rapidjson; 39 | namespace kc = kiteconnect; 40 | namespace utils = kc::internal::utils; 41 | 42 | /// Represents parameters of a single GTT. 43 | struct gttParams { 44 | GENERATE_FLUENT_METHOD(gttParams, int, quantity, Quantity); 45 | GENERATE_FLUENT_METHOD(gttParams, double, price, Price); 46 | GENERATE_FLUENT_METHOD( 47 | gttParams, const string&, transactionType, TransactionType); 48 | GENERATE_FLUENT_METHOD(gttParams, const string&, orderType, OrderType); 49 | GENERATE_FLUENT_METHOD(gttParams, const string&, product, Product); 50 | 51 | int quantity = -1; 52 | double price = -1; 53 | string transactionType; 54 | string orderType; 55 | string product; 56 | }; 57 | 58 | /// Represents 'condition' for a single gtt. 59 | struct GTTCondition { 60 | GTTCondition() = default; 61 | explicit GTTCondition(const rj::Value::Object& val) { parse(val); }; 62 | 63 | void parse(const rj::Value::Object& val) { 64 | exchange = utils::json::get(val, "exchange"); 65 | tradingsymbol = utils::json::get(val, "tradingsymbol"); 66 | lastPrice = utils::json::get(val, "last_price"); 67 | triggerValues = 68 | utils::json::get>(val, "trigger_values"); 69 | }; 70 | 71 | double lastPrice = -1; 72 | string exchange; 73 | string tradingsymbol; 74 | std::vector triggerValues; 75 | }; 76 | 77 | /// Parameters required for the `placeGtt` method. 78 | struct placeGttParams { 79 | GENERATE_FLUENT_METHOD(placeGttParams, double, lastPrice, LastPrice); 80 | GENERATE_FLUENT_METHOD( 81 | placeGttParams, const string&, triggerType, TriggerType); 82 | GENERATE_FLUENT_METHOD(placeGttParams, const string&, symbol, Symbol); 83 | GENERATE_FLUENT_METHOD(placeGttParams, const string&, exchange, Exchange); 84 | GENERATE_FLUENT_METHOD(placeGttParams, const std::vector&, 85 | triggerValues, TriggerValues); 86 | GENERATE_FLUENT_METHOD(placeGttParams, const std::vector&, 87 | gttParamsList, GttParamsList); 88 | 89 | double lastPrice = -1; 90 | string triggerType; 91 | string symbol; 92 | string exchange; 93 | std::vector triggerValues; 94 | std::vector gttParamsList; 95 | }; 96 | 97 | /// Parameters required for the `modifyGtt` method. 98 | struct modifyGttParams { 99 | GENERATE_FLUENT_METHOD(modifyGttParams, int, triggerId, TriggerId); 100 | GENERATE_FLUENT_METHOD(modifyGttParams, double, lastPrice, LastPrice); 101 | GENERATE_FLUENT_METHOD( 102 | modifyGttParams, const string&, triggerType, TriggerType); 103 | GENERATE_FLUENT_METHOD(modifyGttParams, const string&, symbol, Symbol); 104 | GENERATE_FLUENT_METHOD(modifyGttParams, const string&, exchange, Exchange); 105 | GENERATE_FLUENT_METHOD(modifyGttParams, const std::vector&, 106 | triggerValues, TriggerValues); 107 | GENERATE_FLUENT_METHOD(modifyGttParams, const std::vector&, 108 | gttParamsList, GttParamsList); 109 | 110 | int triggerId; 111 | double lastPrice; 112 | string triggerType; 113 | string symbol; 114 | string exchange; 115 | std::vector triggerValues; 116 | std::vector gttParamsList; 117 | }; 118 | 119 | /// `GTT` represents a single GTT order. 120 | struct GTT { 121 | GTT() = default; 122 | explicit GTT(const rj::Value::Object& val) { parse(val); }; 123 | 124 | void parse(const rj::Value::Object& val) { 125 | ID = utils::json::get(val, "id"); 126 | userID = utils::json::get(val, "user_id"); 127 | type = utils::json::get(val, "type"); 128 | createdAt = utils::json::get(val, "created_at"); 129 | updatedAt = utils::json::get(val, "updated_at"); 130 | expiresAt = utils::json::get(val, "expires_at"); 131 | status = utils::json::get(val, "status"); 132 | condition = utils::json::get( 133 | val, "condition"); 134 | 135 | rj::Value ordersBuffer(rj::kArrayType); 136 | utils::json::get(val, ordersBuffer, "orders"); 137 | for (auto& v : ordersBuffer.GetArray()) { 138 | orders.emplace_back(v.GetObject()); 139 | }; 140 | }; 141 | 142 | int ID = -1; 143 | string userID; 144 | string type; 145 | string createdAt; 146 | string updatedAt; 147 | string expiresAt; 148 | string status; 149 | GTTCondition condition; 150 | std::vector orders; 151 | }; 152 | } // namespace kiteconnect -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Kite Connect API C++ client 2 | 3 | - [Overview](https://github.com/zerodha/cppkiteconnect#overview) 4 | - [Dependencies](https://github.com/zerodha/cppkiteconnect#dependencies) 5 | - [Getting dependencies](https://github.com/zerodha/cppkiteconnect#getting-dependencies) 6 | - [Linux](https://github.com/zerodha/cppkiteconnect#linux) 7 | - [Others & uWS v0.14](https://github.com/zerodha/cppkiteconnect#others--uws-v014) 8 | - [Building & installation](https://github.com/zerodha/cppkiteconnect#building--installation) 9 | - [Examples](https://github.com/zerodha/cppkiteconnect#examples) 10 | - [REST API](https://github.com/zerodha/cppkiteconnect#rest-api) 11 | - [Ticker](https://github.com/zerodha/cppkiteconnect#ticker) 12 | - [Documentation](https://github.com/zerodha/cppkiteconnect#documentation) 13 | - [License](https://github.com/zerodha/cppkiteconnect#license) 14 | 15 | ## Overview 16 | 17 | The official C++ client for communicating with [Kite Connect API](https://kite.trade/). 18 | 19 | CPPKiteConnect is a header-only library that wraps around Zerodha's KiteConnect REST API and WebSockets API. It saves you the hassle of directly communicating with the APIs and provides an easy to use, native and modern C++ interface. 20 | 21 | ## Dependencies 22 | 23 | CPPKiteConnect requires C++17 and following dependancies: 24 | 25 | - [OpenSSL (devel)](https://github.com/openssl/openssl "OpenSSL") 26 | - [uWebSockets v0.14 (devel)](https://github.com/uNetworking/uWebSockets/tree/v0.14) and [its dependancies](https://github.com/hoytech/uWebSockets/blob/master/docs/Misc.-details.md#dependencies). 27 | - [googletest](https://github.com/google/googletest) and [googlemock](https://github.com/google/googletest) are required for running tests. 28 | - Doxygen is required for generating documentation. 29 | 30 | ## Getting dependencies 31 | 32 | ### Linux 33 | 34 | - On Fedora 32: 35 | `sudo dnf install openssl-devel zlib-devel` + (uWS v0.14) + (`gtest-devel gmock-devel` for running tests) 36 | - On Ubuntu: 37 | `sudo apt install libssl-dev zlib1g-dev` + (uWS v0.14) + (googletest, googlemock for running tests) 38 | 39 | ### Others & uWS v0.14 40 | 41 | Use package managers provided by your OS. Unless your package manager provides `v0.14` of `uWS`, you'll have to build and install it manually. 42 | 43 | You can also download source of the required dependencies by running `cmake .` in `deps` directory. This will place files in the same directory. 44 | 45 | ## Building & Installation 46 | 47 | Clone the repository and fetch the submodules 48 | 49 | ```sh 50 | git clone https://github.com/zerodha/cppkiteconnect.git 51 | submodule update --init --recursive 52 | ``` 53 | 54 | CPPKiteConnect is a header-only library. Copy the `include` folder to system or project's include path. 55 | 56 | ### Build 57 | 58 | ```bash 59 | mkdir build && cd build 60 | cmake .. -DBUILD_TESTS=On 61 | make 62 | ``` 63 | 64 | If `cmake` cannot find your `uWS` library, try providing it manually to `cmake` like `cmake .. -DUWS_LIB=/path/to/uWS.so`. Note that this will build the library but some tests might not be run. 65 | 66 | #### Build options 67 | 68 | | Option | Description | 69 | | :-------------- | ----------: | 70 | | `BUILD_TESTS` | Build tests | 71 | | `BUILD_EXAMPLES` | Build examples | 72 | | `BUILD_DOCS` | Build docs | 73 | 74 | ### Run examples using Docker 75 | 76 | #### Build the image 77 | 78 | In project directory, 79 | 80 | `docker build -t cppkiteconnect-dev .` 81 | 82 | #### Run the built image 83 | 84 | `docker run -it -e EXAMPLE_NUMBER=1 cppkiteconnect-dev` 85 | 86 | ##### env variables 87 | 88 | | Option | Description | 89 | |:--------------------|-----------------------------:| 90 | | `EXAMPLE_NUMBER` | Example to run (e.g., `1` ) | 91 | | `KITE_API_KEY` | Kite API key | 92 | | `KITE_ACCESS_TOKEN` | Kite access token | 93 | | `KITE_API_SECRET` | Kite API secret | 94 | 95 | ### Run tests 96 | 97 | `make && make test ARGS='-V'` 98 | 99 | ### Generate docs 100 | 101 | `make docs` 102 | 103 | ## Examples 104 | 105 | ### REST API 106 | 107 | ```c++ 108 | #include 109 | #include 110 | #include "kitepp.hpp" 111 | 112 | namespace kc = kiteconnect; 113 | 114 | int main() { 115 | try { 116 | kc::kite Kite(std::getenv("KITE_API_KEY")); 117 | std::string apiSecret = std::getenv("KITE_API_SECRET"); 118 | 119 | std::cout << "login URL: " << Kite.loginURL() << '\n'; 120 | std::cout << "login with this URL and obtain the request token\n"; 121 | 122 | std::string reqToken; 123 | std::cout << "enter obtained request token: "; 124 | std::cin >> reqToken; 125 | 126 | std::string accessToken = 127 | Kite.generateSession(reqToken, apiSecret).tokens.accessToken; 128 | Kite.setAccessToken(accessToken); 129 | std::cout << "access token is " << Kite.getAccessToken() << '\n'; 130 | 131 | kc::userProfile profile = Kite.profile(); 132 | std::cout << "name: " << profile.userName << "\n"; 133 | std::cout << "email: " << profile.email << "\n"; 134 | 135 | } catch (kc::kiteppException& e) { 136 | std::cerr << e.what() << ", " << e.code() << ", " << e.message() << '\n'; 137 | } catch (kc::libException& e) { 138 | std::cerr << e.what() << '\n'; 139 | } 140 | catch (std::exception& e) { 141 | std::cerr << e.what() << std::endl; 142 | }; 143 | return 0; 144 | }; 145 | ``` 146 | 147 | ### Ticker 148 | 149 | ```c++ 150 | #include 151 | #include "kitepp.hpp" 152 | 153 | namespace kc = kiteconnect; 154 | 155 | void onConnect(kc::ticker* ws) { 156 | std::cout << "Connected.. Subscribing now..\n"; 157 | ws->setMode("full", { 408065, 2953217 }); 158 | }; 159 | 160 | void onTicks(kc::ticker* ws, const std::vector& ticks) { 161 | for (const auto& i : ticks) { 162 | std::cout << "instrument token: " << i.instrumentToken 163 | << " last price: " << i.lastPrice << "\n"; 164 | }; 165 | }; 166 | 167 | void onError(kc::ticker* ws, int code, const std::string& message) { 168 | std::cout << "Error! Code: " << code << " message: " << message << "\n"; 169 | }; 170 | 171 | void onConnectError(kc::ticker* ws) { std::cout << "Couldn't connect..\n"; }; 172 | 173 | void onClose(kc::ticker* ws, int code, const std::string& message) { 174 | std::cout << "Closed the connection.. code: " << code 175 | << " message: " << message << "\n"; 176 | }; 177 | 178 | int main(int argc, char const* argv[]) { 179 | kc::ticker Ticker(std::getenv("KITE_API_KEY"), 5, true, 5); 180 | 181 | Ticker.setAccessToken(std::getenv("KITE_ACCESS_TOKEN")); 182 | Ticker.onConnect = onConnect; 183 | Ticker.onTicks = onTicks; 184 | Ticker.onError = onError; 185 | Ticker.onConnectError = onConnectError; 186 | Ticker.onClose = onClose; 187 | 188 | Ticker.connect(); 189 | Ticker.run(); 190 | Ticker.stop(); 191 | 192 | return 0; 193 | }; 194 | ``` 195 | 196 | More examples can be found in the [examples directory](https://github.com/zerodha/cppkiteconnect/tree/main/examples). 197 | 198 | ## Documentation 199 | 200 | - [KiteConnect API documentation](https://kite.trade/docs/connect/v3/) 201 | - [CPPKiteConnect reference documentation](https://kite.trade/docs/cppkiteconnect/#documentation) 202 | 203 | ## License 204 | 205 | [MIT](https://opensource.org/licenses/MIT) 206 | -------------------------------------------------------------------------------- /tests/unit/kite/user.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2022 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include "../kitepp.hpp" 37 | #include "../utils.hpp" 38 | 39 | using std::string; 40 | using ::testing::ByMove; 41 | using ::testing::Return; 42 | using ::testing::StrictMock; 43 | namespace kc = kiteconnect; 44 | namespace utils = kc::internal::utils; 45 | 46 | TEST(kiteTest, profile) { 47 | const string JSON = 48 | kc::test::readFile("../tests/mock_responses/profile.json"); 49 | StrictMock Kite; 50 | EXPECT_CALL(Kite, sendReq(utils::http::endpoint { utils::http::METHOD::GET, 51 | "/user/profile" }, 52 | utils::http::Params {}, utils::FmtArgs {})) 53 | .Times(1) 54 | .WillOnce( 55 | Return(ByMove(utils::http::response(utils::http::code::OK, JSON)))); 56 | 57 | kc::userProfile profile = Kite.profile(); 58 | 59 | // Expected values 60 | EXPECT_EQ(profile.userID, "AB1234"); 61 | EXPECT_EQ(profile.userName, "AxAx Bxx"); 62 | EXPECT_EQ(profile.userShortName, "AxAx"); 63 | EXPECT_EQ(profile.avatarURL, ""); 64 | EXPECT_EQ(profile.userType, "individual"); 65 | EXPECT_EQ(profile.email, "xxxyyy@gmail.com"); 66 | EXPECT_EQ(profile.broker, "ZERODHA"); 67 | EXPECT_THAT(profile.products, 68 | ::testing::ElementsAre("CNC", "NRML", "MIS", "BO", "CO")); 69 | EXPECT_THAT(profile.orderTypes, 70 | ::testing::ElementsAre("MARKET", "LIMIT", "SL", "SL-M")); 71 | EXPECT_THAT(profile.exchanges, ::testing::ElementsAre("BFO", "MCX", "NSE", 72 | "CDS", "BSE", "BCD", "MF", "NFO")); 73 | EXPECT_EQ(profile.meta.dematConsent, "physical"); 74 | }; 75 | 76 | TEST(kiteTest, getMarginsTest) { 77 | const string JSON = 78 | kc::test::readFile("../tests/mock_responses/margins.json"); 79 | StrictMock Kite; 80 | EXPECT_CALL(Kite, sendReq(utils::http::endpoint { utils::http::METHOD::GET, 81 | "/user/margins" }, 82 | utils::http::Params {}, utils::FmtArgs {})) 83 | .Times(1) 84 | .WillOnce( 85 | Return(ByMove(utils::http::response(utils::http::code::OK, JSON)))); 86 | 87 | kc::allMargins margins = Kite.getMargins(); 88 | 89 | // Expected values 90 | EXPECT_EQ(margins.equity.enabled, true); 91 | EXPECT_DOUBLE_EQ(margins.equity.net, 99725.050000000017); 92 | 93 | EXPECT_DOUBLE_EQ(margins.equity.available.adHocMargin, 0); 94 | EXPECT_DOUBLE_EQ(margins.equity.available.cash, 245431.60000000001); 95 | EXPECT_DOUBLE_EQ(margins.equity.available.collateral, 0); 96 | EXPECT_DOUBLE_EQ(margins.equity.available.intradayPayin, 0); 97 | 98 | EXPECT_DOUBLE_EQ(margins.equity.used.debits, 145706.54999999999); 99 | EXPECT_DOUBLE_EQ(margins.equity.used.exposure, 38981.25); 100 | EXPECT_DOUBLE_EQ(margins.equity.used.M2MRealised, 761.70000000000005); 101 | EXPECT_DOUBLE_EQ(margins.equity.used.M2MUnrealised, 0); 102 | EXPECT_DOUBLE_EQ(margins.equity.used.optionPremium, 0); 103 | EXPECT_DOUBLE_EQ(margins.equity.used.payout, 0); 104 | EXPECT_DOUBLE_EQ(margins.equity.used.span, 101989); 105 | EXPECT_DOUBLE_EQ(margins.equity.used.holdingSales, 0); 106 | EXPECT_DOUBLE_EQ(margins.equity.used.turnover, 0); 107 | 108 | EXPECT_EQ(margins.commodity.enabled, true); 109 | EXPECT_DOUBLE_EQ(margins.commodity.net, 100661.7); 110 | 111 | EXPECT_DOUBLE_EQ(margins.commodity.available.adHocMargin, 0); 112 | EXPECT_DOUBLE_EQ(margins.commodity.available.cash, 100661.7); 113 | EXPECT_DOUBLE_EQ(margins.commodity.available.collateral, 0); 114 | EXPECT_DOUBLE_EQ(margins.commodity.available.intradayPayin, 0); 115 | 116 | EXPECT_DOUBLE_EQ(margins.commodity.used.debits, 0); 117 | EXPECT_DOUBLE_EQ(margins.commodity.used.exposure, 0); 118 | EXPECT_DOUBLE_EQ(margins.commodity.used.M2MRealised, 0); 119 | EXPECT_DOUBLE_EQ(margins.commodity.used.M2MUnrealised, 0); 120 | EXPECT_DOUBLE_EQ(margins.commodity.used.optionPremium, 0); 121 | EXPECT_DOUBLE_EQ(margins.commodity.used.payout, 0); 122 | EXPECT_DOUBLE_EQ(margins.commodity.used.span, 0); 123 | EXPECT_DOUBLE_EQ(margins.commodity.used.holdingSales, 0); 124 | EXPECT_DOUBLE_EQ(margins.commodity.used.turnover, 0); 125 | } 126 | 127 | TEST(kiteTest, getMarginsSegmentTest) { 128 | const string JSON = 129 | kc::test::readFile("../tests/mock_responses/margins_equity.json"); 130 | const string SEGMENT = "equity"; 131 | 132 | StrictMock Kite; 133 | EXPECT_CALL(Kite, sendReq(utils::http::endpoint { utils::http::METHOD::GET, 134 | "/user/margins/{0}" }, 135 | utils::http::Params {}, utils::FmtArgs { SEGMENT })) 136 | .Times(1) 137 | .WillOnce( 138 | Return(ByMove(utils::http::response(utils::http::code::OK, JSON)))); 139 | 140 | kc::margins margins = Kite.getMargins(SEGMENT); 141 | 142 | // Expected values 143 | EXPECT_EQ(margins.enabled, true); 144 | EXPECT_DOUBLE_EQ(margins.net, 99725.050000000017); 145 | 146 | EXPECT_DOUBLE_EQ(margins.available.adHocMargin, 0); 147 | EXPECT_DOUBLE_EQ(margins.available.cash, 245431.60000000001); 148 | EXPECT_DOUBLE_EQ(margins.available.collateral, 0); 149 | EXPECT_DOUBLE_EQ(margins.available.intradayPayin, 0); 150 | 151 | EXPECT_DOUBLE_EQ(margins.used.debits, 145706.54999999999); 152 | EXPECT_DOUBLE_EQ(margins.used.exposure, 38981.25); 153 | EXPECT_DOUBLE_EQ(margins.used.M2MRealised, 761.70000000000005); 154 | EXPECT_DOUBLE_EQ(margins.used.M2MUnrealised, 0); 155 | EXPECT_DOUBLE_EQ(margins.used.optionPremium, 0); 156 | EXPECT_DOUBLE_EQ(margins.used.payout, 0); 157 | EXPECT_DOUBLE_EQ(margins.used.span, 101989); 158 | EXPECT_DOUBLE_EQ(margins.used.holdingSales, 0); 159 | EXPECT_DOUBLE_EQ(margins.used.turnover, 0); 160 | } -------------------------------------------------------------------------------- /tests/unit/tickertest.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2022 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | 32 | #include "kitepp.hpp" 33 | 34 | namespace kiteconnect { 35 | 36 | namespace kc = kiteconnect; 37 | 38 | TEST(tickerTest, binaryParsingTest) { 39 | kc::ticker Ticker("apikey123"); 40 | std::ifstream dataFile("../tests/mock_custom/websocket_ticks.bin"); 41 | ASSERT_TRUE(dataFile); 42 | std::vector data(std::istreambuf_iterator(dataFile), {}); 43 | 44 | std::vector ticks = 45 | Ticker.parseBinaryMessage(data.data(), data.size()); 46 | 47 | ASSERT_EQ(ticks.size(), 2); 48 | kc::tick tick1 = ticks[0]; 49 | EXPECT_EQ(tick1.mode, "full"); 50 | EXPECT_EQ(tick1.instrumentToken, 408065); 51 | EXPECT_EQ(tick1.isTradable, true); 52 | EXPECT_EQ(tick1.timestamp, 1612777255); 53 | EXPECT_EQ(tick1.lastTradeTime, 1612777255); 54 | EXPECT_DOUBLE_EQ(tick1.lastPrice, 1299.05); 55 | EXPECT_EQ(tick1.lastTradedQuantity, 2); 56 | EXPECT_EQ(tick1.totalBuyQuantity, 390117); 57 | EXPECT_EQ(tick1.totalSellQuantity, 410173); 58 | EXPECT_EQ(tick1.volumeTraded, 6065675); 59 | EXPECT_DOUBLE_EQ(tick1.averageTradePrice, 1290.29); 60 | EXPECT_EQ(tick1.oi, 0); 61 | EXPECT_EQ(tick1.oiDayHigh, 0); 62 | EXPECT_EQ(tick1.oiDayLow, 0); 63 | EXPECT_DOUBLE_EQ(tick1.netChange, 2.1185441396116693); 64 | 65 | EXPECT_DOUBLE_EQ(tick1.ohlc.open, 1285.5); 66 | EXPECT_DOUBLE_EQ(tick1.ohlc.high, 1305.90); 67 | EXPECT_DOUBLE_EQ(tick1.ohlc.low, 1275.5); 68 | EXPECT_DOUBLE_EQ(tick1.ohlc.close, 1272.1); 69 | 70 | EXPECT_DOUBLE_EQ(tick1.marketDepth.buy[0].price, 1299); 71 | EXPECT_EQ(tick1.marketDepth.buy[0].quantity, 2098); 72 | EXPECT_EQ(tick1.marketDepth.buy[0].orders, 10); 73 | 74 | EXPECT_DOUBLE_EQ(tick1.marketDepth.buy[1].price, 1298.90); 75 | EXPECT_EQ(tick1.marketDepth.buy[1].quantity, 6); 76 | EXPECT_EQ(tick1.marketDepth.buy[1].orders, 2); 77 | 78 | EXPECT_DOUBLE_EQ(tick1.marketDepth.buy[2].price, 1298.8); 79 | EXPECT_EQ(tick1.marketDepth.buy[2].quantity, 135); 80 | EXPECT_EQ(tick1.marketDepth.buy[2].orders, 5); 81 | 82 | EXPECT_DOUBLE_EQ(tick1.marketDepth.buy[3].price, 1298.75); 83 | EXPECT_EQ(tick1.marketDepth.buy[3].quantity, 1); 84 | EXPECT_EQ(tick1.marketDepth.buy[3].orders, 1); 85 | 86 | EXPECT_DOUBLE_EQ(tick1.marketDepth.buy[4].price, 1298.7); 87 | EXPECT_EQ(tick1.marketDepth.buy[4].quantity, 55); 88 | EXPECT_EQ(tick1.marketDepth.buy[4].orders, 2); 89 | 90 | EXPECT_DOUBLE_EQ(tick1.marketDepth.sell[0].price, 1299.05); 91 | EXPECT_EQ(tick1.marketDepth.sell[0].quantity, 335); 92 | EXPECT_EQ(tick1.marketDepth.sell[0].orders, 7); 93 | 94 | EXPECT_DOUBLE_EQ(tick1.marketDepth.sell[1].price, 1299.1); 95 | EXPECT_EQ(tick1.marketDepth.sell[1].quantity, 1); 96 | EXPECT_EQ(tick1.marketDepth.sell[1].orders, 1); 97 | 98 | EXPECT_DOUBLE_EQ(tick1.marketDepth.sell[2].price, 1299.4); 99 | EXPECT_EQ(tick1.marketDepth.sell[2].quantity, 45); 100 | EXPECT_EQ(tick1.marketDepth.sell[2].orders, 2); 101 | 102 | EXPECT_DOUBLE_EQ(tick1.marketDepth.sell[3].price, 1299.45); 103 | EXPECT_EQ(tick1.marketDepth.sell[3].quantity, 120); 104 | EXPECT_EQ(tick1.marketDepth.sell[3].orders, 2); 105 | 106 | EXPECT_DOUBLE_EQ(tick1.marketDepth.sell[4].price, 1299.5); 107 | EXPECT_EQ(tick1.marketDepth.sell[4].quantity, 233); 108 | EXPECT_EQ(tick1.marketDepth.sell[4].orders, 3); 109 | 110 | kc::tick tick2 = ticks[1]; 111 | EXPECT_EQ(tick2.mode, "full"); 112 | EXPECT_EQ(tick2.instrumentToken, 2953217); 113 | EXPECT_EQ(tick2.isTradable, true); 114 | EXPECT_EQ(tick2.timestamp, 1612777254); 115 | EXPECT_EQ(tick2.lastTradeTime, 1612777254); 116 | EXPECT_DOUBLE_EQ(tick2.lastPrice, 3209.40); 117 | EXPECT_EQ(tick2.lastTradedQuantity, 148); 118 | EXPECT_EQ(tick2.totalBuyQuantity, 146646); 119 | EXPECT_EQ(tick2.totalSellQuantity, 145876); 120 | EXPECT_EQ(tick2.volumeTraded, 2261635); 121 | EXPECT_DOUBLE_EQ(tick2.averageTradePrice, 3188.32); 122 | EXPECT_EQ(tick2.oi, 0); 123 | EXPECT_EQ(tick2.oiDayHigh, 0); 124 | EXPECT_EQ(tick2.oiDayLow, 0); 125 | EXPECT_DOUBLE_EQ(tick2.netChange, 1.6292214886239578); 126 | 127 | EXPECT_DOUBLE_EQ(tick2.ohlc.open, 3189.5); 128 | EXPECT_DOUBLE_EQ(tick2.ohlc.high, 3226); 129 | EXPECT_DOUBLE_EQ(tick2.ohlc.low, 3155.15); 130 | EXPECT_DOUBLE_EQ(tick2.ohlc.close, 3157.95); 131 | 132 | EXPECT_DOUBLE_EQ(tick2.marketDepth.buy[0].price, 3209.7); 133 | EXPECT_EQ(tick2.marketDepth.buy[0].quantity, 1); 134 | EXPECT_EQ(tick2.marketDepth.buy[0].orders, 1); 135 | 136 | EXPECT_DOUBLE_EQ(tick2.marketDepth.buy[1].price, 3209.4); 137 | EXPECT_EQ(tick2.marketDepth.buy[1].quantity, 300); 138 | EXPECT_EQ(tick2.marketDepth.buy[1].orders, 1); 139 | 140 | EXPECT_DOUBLE_EQ(tick2.marketDepth.buy[2].price, 3209.25); 141 | EXPECT_EQ(tick2.marketDepth.buy[2].quantity, 138); 142 | EXPECT_EQ(tick2.marketDepth.buy[2].orders, 1); 143 | 144 | EXPECT_DOUBLE_EQ(tick2.marketDepth.buy[3].price, 3209.15); 145 | EXPECT_EQ(tick2.marketDepth.buy[3].quantity, 31); 146 | EXPECT_EQ(tick2.marketDepth.buy[3].orders, 1); 147 | 148 | EXPECT_DOUBLE_EQ(tick2.marketDepth.buy[4].price, 3209.05); 149 | EXPECT_EQ(tick2.marketDepth.buy[4].quantity, 52); 150 | EXPECT_EQ(tick2.marketDepth.buy[4].orders, 1); 151 | 152 | EXPECT_DOUBLE_EQ(tick2.marketDepth.sell[0].price, 3209.95); 153 | EXPECT_EQ(tick2.marketDepth.sell[0].quantity, 16); 154 | EXPECT_EQ(tick2.marketDepth.sell[0].orders, 2); 155 | 156 | EXPECT_DOUBLE_EQ(tick2.marketDepth.sell[1].price, 3210.05); 157 | EXPECT_EQ(tick2.marketDepth.sell[1].quantity, 35); 158 | EXPECT_EQ(tick2.marketDepth.sell[1].orders, 1); 159 | 160 | EXPECT_DOUBLE_EQ(tick2.marketDepth.sell[2].price, 3210.1); 161 | EXPECT_EQ(tick2.marketDepth.sell[2].quantity, 47); 162 | EXPECT_EQ(tick2.marketDepth.sell[2].orders, 2); 163 | 164 | EXPECT_DOUBLE_EQ(tick2.marketDepth.sell[3].price, 3210.15); 165 | EXPECT_EQ(tick2.marketDepth.sell[3].quantity, 30); 166 | EXPECT_EQ(tick2.marketDepth.sell[3].orders, 3); 167 | 168 | EXPECT_DOUBLE_EQ(tick2.marketDepth.sell[4].price, 3210.2); 169 | EXPECT_EQ(tick2.marketDepth.sell[4].quantity, 670); 170 | EXPECT_EQ(tick2.marketDepth.sell[4].orders, 1); 171 | }; 172 | } // namespace kiteconnect 173 | -------------------------------------------------------------------------------- /include/kitepp/responses/margins.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2023 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include 30 | 31 | #include "../utils.hpp" 32 | #include "rapidcsv/src/rapidcsv.h" 33 | #include "rapidjson/include/rapidjson/document.h" 34 | #include "rapidjson/include/rapidjson/rapidjson.h" 35 | 36 | namespace kiteconnect { 37 | 38 | using std::string; 39 | namespace rj = rapidjson; 40 | namespace kc = kiteconnect; 41 | namespace utils = kc::internal::utils; 42 | 43 | struct orderCharges { 44 | orderCharges() = default; 45 | explicit orderCharges(const rj::Value::Object& val) { parse(val); }; 46 | 47 | void parse(const rj::Value::Object& val) { 48 | transactionTax = utils::json::get(val, "transaction_tax"); 49 | exchangeTurnoverCharge = 50 | utils::json::get(val, "exchange_turnover_charge"); 51 | sebiTurnoverCharge = 52 | utils::json::get(val, "sebi_turnover_charge"); 53 | brokerage = utils::json::get(val, "brokerage"); 54 | stampDuty = utils::json::get(val, "stamp_duty"); 55 | total = utils::json::get(val, "total"); 56 | transactionTaxType = 57 | utils::json::get(val, "transaction_tax_type"); 58 | gst = utils::json::get(val, "gst"); 59 | }; 60 | 61 | double transactionTax = -1; 62 | double exchangeTurnoverCharge = -1; 63 | double sebiTurnoverCharge = -1; 64 | double brokerage = -1; 65 | double stampDuty = -1; 66 | double total = -1; 67 | string transactionTaxType; 68 | struct Gst { 69 | Gst() = default; 70 | explicit Gst(const rj::Value::Object& val) { parse(val); }; 71 | 72 | void parse(const rj::Value::Object& val) { 73 | igst = utils::json::get(val, "igst"); 74 | cgst = utils::json::get(val, "cgst"); 75 | sgst = utils::json::get(val, "sgst"); 76 | total = utils::json::get(val, "total"); 77 | }; 78 | 79 | double igst = -1; 80 | double cgst = -1; 81 | double sgst = -1; 82 | double total = -1; 83 | } gst; 84 | }; 85 | 86 | /// Parameters required by the margin methods. 87 | struct marginsParams { 88 | marginsParams() = default; 89 | 90 | GENERATE_FLUENT_METHOD(marginsParams, double, quantity, Quantity); 91 | GENERATE_FLUENT_METHOD(marginsParams, double, price, Price); 92 | GENERATE_FLUENT_METHOD(marginsParams, double, triggerPrice, TriggerPrice); 93 | GENERATE_FLUENT_METHOD(marginsParams, const string&, exchange, Exchange); 94 | GENERATE_FLUENT_METHOD( 95 | marginsParams, const string&, tradingsymbol, Tradingsymbol); 96 | GENERATE_FLUENT_METHOD( 97 | marginsParams, const string&, transactionType, TransactionType); 98 | GENERATE_FLUENT_METHOD(marginsParams, const string&, variety, Variety); 99 | GENERATE_FLUENT_METHOD(marginsParams, const string&, product, Product); 100 | GENERATE_FLUENT_METHOD(marginsParams, const string&, orderType, OrderType); 101 | 102 | double quantity = 0; 103 | double price = 0; 104 | double triggerPrice = 0; 105 | string exchange; 106 | string tradingsymbol; 107 | string transactionType; 108 | string variety; 109 | string product; 110 | string orderType; 111 | }; 112 | 113 | /// Represents margins required for placing an order. 114 | struct orderMargins { 115 | orderMargins() = default; 116 | explicit orderMargins(const rj::Value::Object& val) { parse(val); }; 117 | 118 | void parse(const rj::Value::Object& val) { 119 | type = utils::json::get(val, "type"); 120 | tradingSymbol = utils::json::get(val, "tradingsymbol"); 121 | exchange = utils::json::get(val, "exchange"); 122 | span = utils::json::get(val, "span"); 123 | exposure = utils::json::get(val, "exposure"); 124 | optionPremium = utils::json::get(val, "option_premium"); 125 | additional = utils::json::get(val, "additional"); 126 | bo = utils::json::get(val, "bo"); 127 | cash = utils::json::get(val, "cash"); 128 | var = utils::json::get(val, "var"); 129 | pnl = utils::json::get(val, "pnl"); 130 | total = utils::json::get(val, "total"); 131 | leverage = utils::json::get(val, "leverage"); 132 | charges = utils::json::get( 133 | val, "charges"); 134 | }; 135 | 136 | double span = -1; 137 | double exposure = -1; 138 | double optionPremium = -1; 139 | double additional = -1; 140 | double bo = -1; 141 | double cash = -1; 142 | double var = -1; 143 | double total = -1; 144 | double leverage = -1; 145 | string type; 146 | string tradingSymbol; 147 | string exchange; 148 | struct PNL { 149 | PNL() = default; 150 | explicit PNL(const rj::Value::Object& val) { parse(val); }; 151 | 152 | void parse(const rj::Value::Object& val) { 153 | realised = utils::json::get(val, "realised"); 154 | unrealised = utils::json::get(val, "unrealised"); 155 | }; 156 | 157 | double realised = -1; 158 | double unrealised = -1; 159 | } pnl; 160 | orderCharges charges; 161 | }; 162 | 163 | struct basketMargins { 164 | basketMargins() = default; 165 | explicit basketMargins(const rj::Value::Object& val) { parse(val); }; 166 | 167 | void parse(const rj::Value::Object& val) { 168 | initial = utils::json::get( 169 | val, "initial"); 170 | final = utils::json::get( 171 | val, "final"); 172 | charges = utils::json::get( 173 | val, "charges"); 174 | 175 | rj::Value ordersVal(rj::kArrayType); 176 | utils::json::get(val, ordersVal, "orders"); 177 | for (auto& i : ordersVal.GetArray()) { 178 | orders.emplace_back(i.GetObject()); 179 | }; 180 | }; 181 | 182 | orderMargins initial; 183 | orderMargins final; 184 | std::vector orders; 185 | orderCharges charges; 186 | }; 187 | } // namespace kiteconnect -------------------------------------------------------------------------------- /include/kitepp/responses/user.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2022 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | 30 | #include "../utils.hpp" 31 | #include "rapidjson/include/rapidjson/document.h" 32 | #include "rapidjson/include/rapidjson/rapidjson.h" 33 | 34 | namespace kiteconnect { 35 | 36 | using std::string; 37 | namespace rj = rapidjson; 38 | namespace kc = kiteconnect; 39 | namespace utils = kc::internal::utils; 40 | 41 | /// Represents an user's profile. 42 | struct userProfile { 43 | userProfile() = default; 44 | explicit userProfile(const rj::Value::Object& val) { parse(val); }; 45 | 46 | void parse(const rj::Value::Object& val) { 47 | userID = utils::json::get(val, "user_id"); 48 | userName = utils::json::get(val, "user_name"); 49 | userShortName = utils::json::get(val, "user_shortname"); 50 | avatarURL = utils::json::get(val, "avatar_url"); 51 | userType = utils::json::get(val, "user_type"); 52 | email = utils::json::get(val, "email"); 53 | broker = utils::json::get(val, "broker"); 54 | products = utils::json::get>(val, "products"); 55 | orderTypes = utils::json::get>(val, "order_types"); 56 | exchanges = utils::json::get>(val, "exchanges"); 57 | 58 | meta = utils::json::get(val, "meta"); 59 | }; 60 | 61 | string userID; 62 | string userName; 63 | string userShortName; 64 | string avatarURL; 65 | string userType; 66 | string email; 67 | string broker; 68 | std::vector products; 69 | std::vector orderTypes; 70 | std::vector exchanges; 71 | struct Meta { 72 | Meta() = default; 73 | explicit Meta(const rj::Value::Object& val) { parse(val); }; 74 | 75 | void parse(const rj::Value::Object& val) { 76 | dematConsent = utils::json::get(val, "demat_consent"); 77 | } 78 | 79 | string dematConsent; 80 | } meta; 81 | }; 82 | 83 | /// Represents tokens received after successful authentication. 84 | struct userTokens { 85 | userTokens() = default; 86 | explicit userTokens(const rj::Value::Object& val) { parse(val); }; 87 | 88 | void parse(const rj::Value::Object& val) { 89 | userID = utils::json::get(val, "user_id"); 90 | accessToken = utils::json::get(val, "access_token"); 91 | refreshToken = utils::json::get(val, "refresh_token"); 92 | }; 93 | 94 | string userID; 95 | string accessToken; 96 | string refreshToken; 97 | }; 98 | 99 | /// Represents information of a user session. 100 | struct userSession { 101 | userSession() = default; 102 | explicit userSession(const rj::Value::Object& val) { parse(val); }; 103 | 104 | void parse(const rj::Value::Object& val) { 105 | profile.parse(val); 106 | tokens.parse(val); 107 | apiKey = utils::json::get(val, "api_key"); 108 | publicToken = utils::json::get(val, "public_token"); 109 | loginTime = utils::json::get(val, "login_time"); 110 | }; 111 | 112 | string apiKey; 113 | string publicToken; 114 | string loginTime; 115 | userProfile profile; 116 | userTokens tokens; 117 | }; 118 | 119 | /// Represents available margins of a single segment. 120 | struct availableMargins { 121 | availableMargins() = default; 122 | explicit availableMargins(const rj::Value::Object& val) { parse(val); }; 123 | 124 | void parse(const rj::Value::Object& val) { 125 | adHocMargin = utils::json::get(val, "adhoc_margin"); 126 | cash = utils::json::get(val, "cash"); 127 | collateral = utils::json::get(val, "collateral"); 128 | intradayPayin = utils::json::get(val, "intraday_payin"); 129 | }; 130 | 131 | double adHocMargin = -1; 132 | double cash = -1; 133 | double collateral = -1; 134 | double intradayPayin = -1; 135 | }; 136 | 137 | /// Represents used margins of a single segment. 138 | struct usedMargins { 139 | usedMargins() = default; 140 | explicit usedMargins(const rj::Value::Object& val) { parse(val); }; 141 | 142 | void parse(const rj::Value::Object& val) { 143 | debits = utils::json::get(val, "debits"); 144 | exposure = utils::json::get(val, "exposure"); 145 | M2MRealised = utils::json::get(val, "m2m_realised"); 146 | M2MUnrealised = utils::json::get(val, "m2m_unrealised"); 147 | optionPremium = utils::json::get(val, "option_premium"); 148 | payout = utils::json::get(val, "payout"); 149 | span = utils::json::get(val, "span"); 150 | holdingSales = utils::json::get(val, "holding_sales"); 151 | turnover = utils::json::get(val, "turnover"); 152 | }; 153 | 154 | double debits = -1; 155 | double exposure = -1; 156 | double M2MRealised = -1; 157 | double M2MUnrealised = -1; 158 | double optionPremium = -1; 159 | double payout = -1; 160 | double span = -1; 161 | double holdingSales = -1; 162 | double turnover = -1; 163 | }; 164 | 165 | /// Represents user margins for a segment. 166 | struct margins { 167 | margins() = default; 168 | explicit margins(const rj::Value::Object& val) { parse(val); }; 169 | 170 | void parse(const rj::Value::Object& val) { 171 | enabled = utils::json::get(val, "enabled"); 172 | net = utils::json::get(val, "net"); 173 | available = utils::json::get( 174 | val, "available"); 175 | used = utils::json::get( 176 | val, "utilised"); 177 | }; 178 | 179 | double net = -1; 180 | bool enabled = false; 181 | availableMargins available; 182 | usedMargins used; 183 | }; 184 | 185 | /// Represents all margins (equity and commodity). 186 | struct allMargins { 187 | allMargins() = default; 188 | explicit allMargins(const rj::Value::Object& val) { parse(val); }; 189 | 190 | void parse(const rj::Value::Object& val) { 191 | equity = 192 | utils::json::get(val, "equity"); 193 | commodity = utils::json::get( 194 | val, "commodity"); 195 | }; 196 | 197 | margins equity; 198 | margins commodity; 199 | }; 200 | 201 | } // namespace kiteconnect -------------------------------------------------------------------------------- /include/kitepp/responses/portfolio.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2022 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | 30 | #include "../utils.hpp" 31 | #include "rapidjson/include/rapidjson/document.h" 32 | #include "rapidjson/include/rapidjson/rapidjson.h" 33 | 34 | namespace kiteconnect { 35 | 36 | using std::string; 37 | namespace rj = rapidjson; 38 | namespace kc = kiteconnect; 39 | namespace utils = kc::internal::utils; 40 | 41 | /// Respresents an individual holding. 42 | struct holding { 43 | holding() = default; 44 | explicit holding(const rj::Value::Object& val) { parse(val); }; 45 | 46 | void parse(const rj::Value::Object& val) { 47 | tradingsymbol = utils::json::get(val, "tradingsymbol"); 48 | exchange = utils::json::get(val, "exchange"); 49 | instrumentToken = utils::json::get(val, "instrument_token"); 50 | ISIN = utils::json::get(val, "isin"); 51 | product = utils::json::get(val, "product"); 52 | price = utils::json::get(val, "price"); 53 | quantity = utils::json::get(val, "quantity"); 54 | t1Quantity = utils::json::get(val, "t1_quantity"); 55 | realisedQuantity = utils::json::get(val, "realised_quantity"); 56 | collateralQuantity = utils::json::get(val, "collateral_quantity"); 57 | collateralType = utils::json::get(val, "collateral_type"); 58 | averagePrice = utils::json::get(val, "average_price"); 59 | lastPrice = utils::json::get(val, "last_price"); 60 | closePrice = utils::json::get(val, "close_price"); 61 | PnL = utils::json::get(val, "pnl"); 62 | dayChange = utils::json::get(val, "day_change"); 63 | dayChangePercentage = 64 | utils::json::get(val, "day_change_percentage"); 65 | }; 66 | 67 | uint32_t instrumentToken = 0; 68 | int quantity = -1; 69 | int t1Quantity = -1; 70 | int realisedQuantity = -1; 71 | int collateralQuantity = -1; 72 | double price = -1; 73 | double averagePrice = -1; 74 | double lastPrice = -1; 75 | double closePrice = -1; 76 | double PnL = -1; 77 | double dayChange = -1; 78 | double dayChangePercentage = -1; 79 | string tradingsymbol; 80 | string exchange; 81 | string ISIN; 82 | string product; 83 | string collateralType; 84 | }; 85 | 86 | /// Represents an individual position. 87 | struct position { 88 | position() = default; 89 | explicit position(const rj::Value::Object& val) { parse(val); }; 90 | 91 | void parse(const rj::Value::Object& val) { 92 | tradingsymbol = utils::json::get(val, "tradingsymbol"); 93 | exchange = utils::json::get(val, "exchange"); 94 | instrumentToken = utils::json::get(val, "instrument_token"); 95 | product = utils::json::get(val, "product"); 96 | quantity = utils::json::get(val, "quantity"); 97 | overnightQuantity = utils::json::get(val, "overnight_quantity"); 98 | multiplier = utils::json::get(val, "multiplier"); 99 | averagePrice = utils::json::get(val, "average_price"); 100 | closePrice = utils::json::get(val, "close_price"); 101 | lastPrice = utils::json::get(val, "last_price"); 102 | value = utils::json::get(val, "value"); 103 | PnL = utils::json::get(val, "pnl"); 104 | M2M = utils::json::get(val, "m2m"); 105 | unrealised = utils::json::get(val, "unrealised"); 106 | realised = utils::json::get(val, "realised"); 107 | buyQuantity = utils::json::get(val, "buy_quantity"); 108 | buyPrice = utils::json::get(val, "buy_price"); 109 | buyValue = utils::json::get(val, "buy_value"); 110 | buyM2MValue = utils::json::get(val, "buy_m2m"); 111 | sellQuantity = utils::json::get(val, "sell_quantity"); 112 | sellPrice = utils::json::get(val, "sell_price"); 113 | sellValue = utils::json::get(val, "sell_value"); 114 | sellM2MValue = utils::json::get(val, "sell_m2m"); 115 | dayBuyQuantity = utils::json::get(val, "day_buy_quantity"); 116 | dayBuyPrice = utils::json::get(val, "day_buy_price"); 117 | dayBuyValue = utils::json::get(val, "day_buy_value"); 118 | daySellQuantity = utils::json::get(val, "day_sell_quantity"); 119 | daySellPrice = utils::json::get(val, "day_sell_price"); 120 | daySellValue = utils::json::get(val, "day_sell_value"); 121 | }; 122 | 123 | uint32_t instrumentToken = 0; 124 | int quantity = -1; 125 | int buyQuantity = -1; 126 | int overnightQuantity = -1; 127 | int sellQuantity = -1; 128 | int dayBuyQuantity = -1; 129 | int daySellQuantity = -1; 130 | double multiplier = -1; 131 | double averagePrice = -1; 132 | double closePrice = -1; 133 | double lastPrice = -1; 134 | double value = -1; 135 | double PnL = -1; 136 | double M2M = -1; 137 | double unrealised = -1; 138 | double realised = -1; 139 | double buyPrice = -1; 140 | double buyValue = -1; 141 | double buyM2MValue = -1; 142 | double sellPrice = -1; 143 | double sellValue = -1; 144 | double sellM2MValue = -1; 145 | double dayBuyPrice = -1; 146 | double dayBuyValue = -1; 147 | double daySellPrice = -1; 148 | double daySellValue = -1; 149 | string tradingsymbol; 150 | string exchange; 151 | string product; 152 | }; 153 | 154 | /// Represents response of the `getPositions()` method. 155 | struct positions { 156 | positions() = default; 157 | explicit positions(const rj::Value::Object& val) { parse(val); }; 158 | 159 | void parse(const rj::Value::Object& val) { 160 | rj::Value netVal(rj::kArrayType); 161 | utils::json::get(val, netVal, "net"); 162 | for (auto& i : netVal.GetArray()) { net.emplace_back(i.GetObject()); }; 163 | 164 | rj::Value dayVal(rj::kArrayType); 165 | utils::json::get(val, dayVal, "day"); 166 | for (auto& i : dayVal.GetArray()) { day.emplace_back(i.GetObject()); }; 167 | }; 168 | 169 | std::vector net; 170 | std::vector day; 171 | }; 172 | 173 | /// Parameters required for the `convertPosition()` method. 174 | struct convertPositionParams { 175 | GENERATE_FLUENT_METHOD(convertPositionParams, int, quantity, Quantity); 176 | GENERATE_FLUENT_METHOD( 177 | convertPositionParams, const string&, exchange, Exchange); 178 | GENERATE_FLUENT_METHOD( 179 | convertPositionParams, const string&, symbol, Symbol); 180 | GENERATE_FLUENT_METHOD( 181 | convertPositionParams, const string&, transactionType, TransactionType); 182 | GENERATE_FLUENT_METHOD( 183 | convertPositionParams, const string&, positionType, PositionType); 184 | GENERATE_FLUENT_METHOD( 185 | convertPositionParams, const string&, oldProduct, OldProduct); 186 | GENERATE_FLUENT_METHOD( 187 | convertPositionParams, const string&, newProduct, NewProduct); 188 | 189 | int quantity = -1; 190 | string exchange; 191 | string symbol; 192 | string transactionType; 193 | string positionType; 194 | string oldProduct; 195 | string newProduct; 196 | }; 197 | 198 | } // namespace kiteconnect -------------------------------------------------------------------------------- /include/kitepp/responses/order.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2022 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include 30 | 31 | #include "../utils.hpp" 32 | #include "rapidjson/include/rapidjson/document.h" 33 | #include "rapidjson/include/rapidjson/rapidjson.h" 34 | 35 | namespace kiteconnect { 36 | 37 | using std::string; 38 | namespace rj = rapidjson; 39 | namespace kc = kiteconnect; 40 | namespace utils = kc::internal::utils; 41 | 42 | /// Parameters required for the `placeOrder` method. 43 | struct placeOrderParams { 44 | GENERATE_FLUENT_METHOD(placeOrderParams, int, quantity, Quantity); 45 | GENERATE_FLUENT_METHOD( 46 | placeOrderParams, int, disclosedQuantity, DisclosedQuantity); 47 | GENERATE_FLUENT_METHOD(placeOrderParams, int, validityTtl, ValidityTtl); 48 | GENERATE_FLUENT_METHOD(placeOrderParams, int, icebergLegs, IcebergLegs); 49 | GENERATE_FLUENT_METHOD( 50 | placeOrderParams, int, icebergQuantity, IcebergQuantity); 51 | GENERATE_FLUENT_METHOD(placeOrderParams, double, price, Price); 52 | GENERATE_FLUENT_METHOD( 53 | placeOrderParams, double, triggerPrice, TriggerPrice); 54 | GENERATE_FLUENT_METHOD(placeOrderParams, double, squareOff, SquareOff); 55 | GENERATE_FLUENT_METHOD(placeOrderParams, double, stopLoss, StopLoss); 56 | GENERATE_FLUENT_METHOD( 57 | placeOrderParams, double, trailingStopLoss, TrailingStopLoss); 58 | GENERATE_FLUENT_METHOD(placeOrderParams, const string&, variety, Variety); 59 | GENERATE_FLUENT_METHOD(placeOrderParams, const string&, exchange, Exchange); 60 | GENERATE_FLUENT_METHOD(placeOrderParams, const string&, symbol, Symbol); 61 | GENERATE_FLUENT_METHOD( 62 | placeOrderParams, const string&, transactionType, TransactionType); 63 | GENERATE_FLUENT_METHOD(placeOrderParams, const string&, product, Product); 64 | GENERATE_FLUENT_METHOD( 65 | placeOrderParams, const string&, orderType, OrderType); 66 | GENERATE_FLUENT_METHOD(placeOrderParams, const string&, validity, Validity); 67 | GENERATE_FLUENT_METHOD(placeOrderParams, const string&, tag, Tag); 68 | 69 | int quantity; 70 | std::optional disclosedQuantity; 71 | std::optional validityTtl; 72 | std::optional icebergLegs; 73 | std::optional icebergQuantity; 74 | std::optional price; 75 | std::optional triggerPrice; 76 | std::optional squareOff; 77 | std::optional stopLoss; 78 | std::optional trailingStopLoss; 79 | string variety; 80 | string exchange; 81 | string symbol; 82 | string transactionType; 83 | string product; 84 | string orderType; 85 | std::optional validity; 86 | std::optional tag; 87 | }; 88 | 89 | /// Parameters required for the `modifyOrder` method. 90 | struct modifyOrderParams { 91 | GENERATE_FLUENT_METHOD(modifyOrderParams, int, quantity, Quantity); 92 | GENERATE_FLUENT_METHOD( 93 | modifyOrderParams, int, disclosedQuantity, DisclosedQuantity); 94 | GENERATE_FLUENT_METHOD(modifyOrderParams, double, price, Price); 95 | GENERATE_FLUENT_METHOD( 96 | modifyOrderParams, double, triggerPrice, TriggerPrice); 97 | GENERATE_FLUENT_METHOD(modifyOrderParams, const string&, variety, Variety); 98 | GENERATE_FLUENT_METHOD( 99 | modifyOrderParams, const string&, orderType, OrderType); 100 | GENERATE_FLUENT_METHOD( 101 | modifyOrderParams, const string&, validity, Validity); 102 | GENERATE_FLUENT_METHOD(modifyOrderParams, const string&, orderId, OrderId); 103 | GENERATE_FLUENT_METHOD( 104 | modifyOrderParams, const string&, parentOrderId, ParentOrderId); 105 | 106 | std::optional quantity; 107 | std::optional disclosedQuantity; 108 | std::optional price; 109 | std::optional triggerPrice; 110 | string variety; 111 | string orderId; 112 | std::optional parentOrderId; 113 | std::optional orderType; 114 | std::optional validity; 115 | }; 116 | 117 | /// Represents information of an order. 118 | struct order { 119 | order() = default; 120 | explicit order(const rj::Value::Object& val) { parse(val); }; 121 | 122 | void parse(const rj::Value::Object& val) { 123 | accountID = utils::json::get(val, "account_id"); 124 | placedBy = utils::json::get(val, "placed_by"); 125 | orderID = utils::json::get(val, "order_id"); 126 | exchangeOrderID = utils::json::get(val, "exchange_order_id"); 127 | parentOrderID = utils::json::get(val, "parent_order_id"); 128 | status = utils::json::get(val, "status"); 129 | statusMessage = utils::json::get(val, "status_message"); 130 | orderTimestamp = utils::json::get(val, "order_timestamp"); 131 | exchangeUpdateTimestamp = 132 | utils::json::get(val, "exchange_update_timestamp"); 133 | exchangeTimestamp = utils::json::get(val, "exchange_timestamp"); 134 | rejectedBy = utils::json::get(val, "rejected_by"); 135 | variety = utils::json::get(val, "variety"); 136 | exchange = utils::json::get(val, "exchange"); 137 | tradingsymbol = utils::json::get(val, "tradingsymbol"); 138 | instrumentToken = utils::json::get(val, "instrument_token"); 139 | orderType = utils::json::get(val, "order_type"); 140 | transactionType = utils::json::get(val, "transaction_type"); 141 | validity = utils::json::get(val, "validity"); 142 | product = utils::json::get(val, "product"); 143 | quantity = utils::json::get(val, "quantity"); 144 | disclosedQuantity = utils::json::get(val, "disclosed_quantity"); 145 | validityTtl = utils::json::get(val, "validity_ttl"); 146 | price = utils::json::get(val, "price"); 147 | triggerPrice = utils::json::get(val, "trigger_price"); 148 | averagePrice = utils::json::get(val, "average_price"); 149 | filledQuantity = utils::json::get(val, "filled_quantity"); 150 | pendingQuantity = utils::json::get(val, "pending_quantity"); 151 | cancelledQuantity = utils::json::get(val, "cancelled_quantity"); 152 | }; 153 | 154 | uint32_t instrumentToken = 0; 155 | int quantity = -1; 156 | int disclosedQuantity = -1; 157 | int filledQuantity = -1; 158 | int pendingQuantity = -1; 159 | int cancelledQuantity = -1; 160 | int validityTtl = -1; 161 | double price = -1.0; 162 | double triggerPrice = -1.0; 163 | double averagePrice = -1.0; 164 | string accountID; 165 | string placedBy; 166 | string orderID; 167 | string exchangeOrderID; 168 | string parentOrderID; 169 | string status; 170 | string statusMessage; 171 | string orderTimestamp; 172 | string exchangeUpdateTimestamp; 173 | string exchangeTimestamp; 174 | string rejectedBy; 175 | string variety; 176 | string exchange; 177 | string tradingsymbol; 178 | string orderType; 179 | string transactionType; 180 | string validity; 181 | string product; 182 | }; 183 | 184 | /// Represents information of a trade. 185 | struct trade { 186 | trade() = default; 187 | explicit trade(const rj::Value::Object& val) { parse(val); }; 188 | 189 | void parse(const rj::Value::Object& val) { 190 | averagePrice = utils::json::get(val, "average_price"); 191 | quantity = utils::json::get(val, "quantity"); 192 | tradeID = utils::json::get(val, "trade_id"); 193 | product = utils::json::get(val, "product"); 194 | fillTimestamp = utils::json::get(val, "fill_timestamp"); 195 | exchangeTimestamp = utils::json::get(val, "exchange_timestamp"); 196 | exchangeOrderID = utils::json::get(val, "exchange_order_id"); 197 | orderID = utils::json::get(val, "order_id"); 198 | transactionType = utils::json::get(val, "transaction_type"); 199 | tradingSymbol = utils::json::get(val, "tradingsymbol"); 200 | exchange = utils::json::get(val, "exchange"); 201 | instrumentToken = utils::json::get(val, "instrument_token"); 202 | }; 203 | 204 | uint32_t instrumentToken = 0; 205 | double averagePrice = -1.0; 206 | double quantity = -1.0; 207 | string tradeID; 208 | string product; 209 | string fillTimestamp; 210 | string exchangeTimestamp; 211 | string exchangeOrderID; 212 | string orderID; 213 | string transactionType; 214 | string tradingSymbol; 215 | string exchange; 216 | }; 217 | 218 | } // namespace kiteconnect -------------------------------------------------------------------------------- /include/kitepp/exceptions.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2022 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | namespace kiteconnect { 33 | 34 | using std::string; 35 | 36 | /// 37 | /// @brief CPPKiteConnect saves you the hassle of detecting API errors by 38 | /// manually checking HTTP codes or JSON error responses. It 39 | /// raises appropriately named exceptions. `kiteppException` is 40 | /// derived from `std::exception`, provides `code()`, `message()` methods and 41 | /// inherits the `what()` method. All kitepp exceptions barring one 42 | /// are derived from this class. Most of the times, this is the exception class 43 | /// you'll want to catch. 44 | /// 45 | /// @attention `libExcpetion` isn't derived from `kiteppException`. 46 | /// 47 | /// @paragraph ex1 example 48 | /// @snippet example2.cpp dealing with kitepp exceptions 49 | /// 50 | class kiteppException : public std::exception { 51 | 52 | public: 53 | kiteppException(int Code_, string Message_) 54 | : Code(Code_), Message(std::move(Message_)) {}; 55 | 56 | /// 57 | /// @brief Provides short descripion of the error. 58 | /// 59 | /// @return const char* short descripion 60 | /// 61 | [[nodiscard]] const char* what() const noexcept override = 0; 62 | 63 | /// 64 | /// @brief Get HTTP code sent by the REST API. 65 | /// 66 | /// @return int HTTP code 67 | /// 68 | [[nodiscard]] int code() const noexcept { return Code; }; 69 | 70 | /// 71 | /// @brief Get error message sent by the REST API. 72 | /// 73 | /// @return const char* error message 74 | /// 75 | [[nodiscard]] const char* message() const noexcept { 76 | return Message.c_str(); 77 | }; 78 | 79 | private: 80 | int Code = 0; 81 | string Message; 82 | }; 83 | 84 | /// @brief Represents all token and authentication related errors. 85 | class tokenException : public kiteppException { 86 | 87 | public: 88 | tokenException(int code, string message) 89 | : kiteppException(code, std::move(message)) {}; 90 | 91 | /// \copydoc kiteconnect::kiteppException::what() 92 | [[nodiscard]] const char* what() const noexcept override { 93 | return "TokenException was thrown by Kite"; 94 | }; 95 | }; 96 | 97 | /// @brief Represents user account related errors. 98 | class userException : public kiteppException { 99 | 100 | public: 101 | userException(int code, string message) 102 | : kiteppException(code, std::move(message)) {}; 103 | 104 | /// \copydoc kiteconnect::kiteppException::what() 105 | [[nodiscard]] const char* what() const noexcept override { 106 | return "UserException was thrown by Kite"; 107 | }; 108 | }; 109 | 110 | /// @brief Represents all order placement and manipulation errors. 111 | class orderException : public kiteppException { 112 | 113 | public: 114 | orderException(int code, string message) 115 | : kiteppException(code, std::move(message)) {}; 116 | 117 | /// \copydoc kiteconnect::kiteppException::what() 118 | [[nodiscard]] const char* what() const noexcept override { 119 | return "OrderException was thrown by Kite"; 120 | }; 121 | }; 122 | 123 | /// @brief Represents user input errors such as missing and invalid parameters. 124 | class inputException : public kiteppException { 125 | 126 | public: 127 | inputException(int code, string message) 128 | : kiteppException(code, std::move(message)) {}; 129 | 130 | /// \copydoc kiteconnect::kiteppException::what() 131 | [[nodiscard]] const char* what() const noexcept override { 132 | return "InputException was thrown by Kite"; 133 | }; 134 | }; 135 | 136 | /// 137 | /// @brief Represents a network issue between Kite and the backend Order 138 | /// Management System (OMS). 139 | /// 140 | class networkException : public kiteppException { 141 | 142 | public: 143 | networkException(int code, string message) 144 | : kiteppException(code, std::move(message)) {}; 145 | 146 | /// \copydoc kiteconnect::kiteppException::what() 147 | [[nodiscard]] const char* what() const noexcept override { 148 | return "NetworkException was thrown by Kite"; 149 | }; 150 | }; 151 | 152 | /// @brief Represents a bad response from the backend Order Management System. 153 | class dataException : public kiteppException { 154 | 155 | public: 156 | dataException(int code, string message) 157 | : kiteppException(code, std::move(message)) {}; 158 | 159 | /// \copydoc kiteconnect::kiteppException::what() 160 | [[nodiscard]] const char* what() const noexcept override { 161 | return "DataException was thrown by Kite"; 162 | }; 163 | }; 164 | 165 | /// @brief An unclassified, general error. 166 | class generalException : public kiteppException { 167 | 168 | public: 169 | generalException(int code, string message) 170 | : kiteppException(code, std::move(message)) {}; 171 | 172 | /// \copydoc kiteconnect::kiteppException::what() 173 | [[nodiscard]] const char* what() const noexcept override { 174 | return "GeneralException was thrown by Kite"; 175 | }; 176 | }; 177 | 178 | /// @brief Represents permission denied exceptions for certain calls. 179 | class permissionException : public kiteppException { 180 | 181 | public: 182 | permissionException(int code, string message) 183 | : kiteppException(code, std::move(message)) {}; 184 | 185 | /// \copydoc kiteconnect::kiteppException::what() 186 | [[nodiscard]] const char* what() const noexcept override { 187 | return "PermissionException was thrown by Kite"; 188 | }; 189 | }; 190 | 191 | /// @brief This exception is thrown when REST API doesn't return a `HTTP OK 200` 192 | /// code but doesn't return any exception string either. 193 | class unknownException : public kiteppException { 194 | 195 | public: 196 | unknownException(int code, string message) 197 | : kiteppException(code, std::move(message)) {}; 198 | 199 | /// \copydoc kiteconnect::kiteppException::what() 200 | [[nodiscard]] const char* what() const noexcept override { 201 | return "unknown exception was thrown by Kite"; 202 | }; 203 | }; 204 | 205 | /// @brief This exception is thrown when an error occures at the library level. 206 | class libException : public std::exception { 207 | 208 | public: 209 | explicit libException(string Message): message(std::move(Message)) {}; 210 | 211 | /// 212 | /// \brief Provides short description of the error. 213 | /// 214 | /// \return const char* short description 215 | /// 216 | const char* what() { return message.c_str(); }; 217 | 218 | private: 219 | string message; 220 | }; 221 | 222 | namespace internal { 223 | inline void throwException( 224 | const string& exceptionString, int code, const string& msg) { 225 | // exception strings sent by API 226 | static const string tokenExceptionString = "TokenException"; 227 | static const string userExceptionString = "UserException"; 228 | static const string orderExcptionString = "OrderException"; 229 | static const string inputExceptionString = "InputException"; 230 | static const string networkExceptionString = "NetworkException"; 231 | static const string dataExceptionString = "DataException"; 232 | static const string generalExceptionString = "GeneralException"; 233 | static const string permissionExceptionString = "PermissionException"; 234 | 235 | // when rest api doesn't send an exception but http status code isn't 200 236 | // either 237 | static const string unknownExceptionString = "NoException"; 238 | 239 | if (exceptionString == tokenExceptionString) { 240 | throw tokenException(code, msg); 241 | }; 242 | if (exceptionString == userExceptionString) { 243 | throw userException(code, msg); 244 | }; 245 | if (exceptionString == orderExcptionString) { 246 | throw orderException(code, msg); 247 | }; 248 | if (exceptionString == inputExceptionString) { 249 | throw inputException(code, msg); 250 | }; 251 | if (exceptionString == networkExceptionString) { 252 | throw networkException(code, msg); 253 | }; 254 | if (exceptionString == dataExceptionString) { 255 | throw dataException(code, msg); 256 | }; 257 | if (exceptionString == generalExceptionString) { 258 | throw generalException(code, msg); 259 | }; 260 | if (exceptionString == permissionExceptionString) { 261 | throw permissionException(code, msg); 262 | }; 263 | if (exceptionString == unknownExceptionString) { 264 | throw unknownException(code, msg); 265 | }; 266 | 267 | throw libException("unknown exception was thrown by REST API"); 268 | }; 269 | } // namespace internal 270 | 271 | } // namespace kiteconnect -------------------------------------------------------------------------------- /include/kitepp/ticker/ws.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2021 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #pragma once 27 | 28 | #include //reverse 29 | #include 30 | #include 31 | #include 32 | #include //memcpy 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #include "../exceptions.hpp" 44 | #include "../responses/responses.hpp" 45 | #include "../userconstants.hpp" //modes 46 | #include "../utils.hpp" 47 | 48 | #include "rapidjson/include/rapidjson/document.h" 49 | #include "rapidjson/include/rapidjson/rapidjson.h" 50 | #include "rapidjson/include/rapidjson/writer.h" 51 | #include 52 | 53 | namespace kiteconnect { 54 | 55 | // To make sure doubles are parsed correctly 56 | static_assert(std::numeric_limits::is_iec559, 57 | "Requires IEEE 754 floating point!"); 58 | 59 | using std::string; 60 | namespace kc = kiteconnect; 61 | 62 | /// 63 | /// \brief \a ticker wraps around the websocket API provided by KiteConnect and 64 | /// provides a native interface. 65 | /// 66 | class ticker { 67 | 68 | public: 69 | // callbacks 70 | /// @brief Called on successful connect. 71 | std::function onConnect; 72 | 73 | /// @brief Called when ticks are received. 74 | std::function& ticks)> onTicks; 75 | 76 | /// @brief Called when an order update is received. 77 | std::function onOrderUpdate; 78 | 79 | /// @brief Called when a message is received. 80 | std::function onMessage; 81 | 82 | /// @brief Called when connection is closed with an error or websocket 83 | /// server sends an error message. 84 | std::function onError; 85 | 86 | /// @brief Called when an error occures while trying to connect. 87 | std::function onConnectError; 88 | 89 | /// 90 | /// @brief Called when reconnection is being attempted. 91 | /// 92 | /// \note Auto reconnection: 93 | /// Auto reconnection is disabled by default and can be enabled by 94 | /// setting `EnableReconnect` to `true` in `ticker`'s constructor. 95 | /// Auto reonnection mechanism is based on exponential backoff 96 | /// algorithm in which next retry interval will be increased 97 | /// exponentially. MaxReconnectDelay and MaxReconnectTries params can 98 | /// be used to tweak the alogrithm. MaxReconnectDelay is the 99 | /// maximum delay after which subsequent reconnection interval will 100 | /// become constant and MaxReconnectTries is maximum number of retries 101 | /// before `ticker` quits trying to reconnect. 102 | /// 103 | std::function onTryReconnect; 104 | 105 | /// 106 | /// @brief Called when reconnect attempts exceed maximum reconnect attempts 107 | /// set by user i.e., when `ticker` is unable to reconnect 108 | /// 109 | std::function onReconnectFail; 110 | 111 | /// @brief Called when connection is closed. 112 | std::function onClose; 113 | 114 | /** 115 | * @brief Construct a new kiteWS object 116 | * 117 | * @param apikey API key 118 | * @param connecttimeout Connection timeout 119 | * @param enablereconnect Should be set to `true` for enabling reconnection 120 | * @param maxreconnectdelay Maximum reconnect delay for reconnection 121 | * @param maxreconnecttries Maximum reconnection attempts after which 122 | * onReconnectFail will be called and no further attempt to reconnect will 123 | * be made. 124 | */ 125 | 126 | /// 127 | /// \brief Construct a new ticker object. All durations are in seconds. 128 | /// 129 | /// \param Key API key 130 | /// \param ConnectTimeout connection timeout 131 | /// \param EnableReconnect auto reconnect is enabled if 132 | /// \a EnableReconnect is set to `true` 133 | /// \param MaxReconnectDelay Maximum delay after which subsequent 134 | /// reconnection interval will become constant 135 | /// \param MaxReconnectTries Maximum number of retries before `ticker` quits 136 | /// trying to reconnect. 137 | /// 138 | explicit ticker(string Key, 139 | unsigned int ConnectTimeout = DEFAULT_CONNECT_TIMEOUT, 140 | bool EnableReconnect = false, 141 | unsigned int MaxReconnectDelay = DEFAULT_MAX_RECONNECT_DELAY, 142 | unsigned int MaxReconnectTries = DEFAULT_MAX_RECONNECT_TRIES); 143 | 144 | /// 145 | /// @brief Set the API key. 146 | /// 147 | /// @param key API key is set to \a key 148 | /// 149 | void setApiKey(const string& key); 150 | 151 | /// 152 | /// @brief Get API key set at the moment. 153 | /// 154 | /// @return string API key 155 | /// 156 | string getApiKey() const; 157 | 158 | /// 159 | /// @brief Set the access token. 160 | /// 161 | /// @param token access token is set to \a token. 162 | /// 163 | /// @paragraph ex1 example 164 | /// @snippet example2.cpp settting access token 165 | /// 166 | void setAccessToken(const string& token); 167 | 168 | /// 169 | /// @brief Get access token set at the moment. 170 | /// 171 | /// @return string access token 172 | /// 173 | string getAccessToken() const; 174 | 175 | /// @brief Connect to the websocket server. 176 | void connect(); 177 | 178 | /// @brief Check if client is connected. 179 | bool isConnected() const; 180 | 181 | /// 182 | /// @brief Get the last time heartbeat was received. Should be used in 183 | /// conjunction with the `isConnected()` method. 184 | /// 185 | /// @return std::chrono::time_point time 186 | /// 187 | std::chrono::time_point getLastBeatTime() const; 188 | 189 | /// @brief Start the client. Should always be called after `connect()`. 190 | void run(); 191 | 192 | /// @brief Stop the client. Closes the connection if connected. Should be 193 | /// the last method that is called. 194 | void stop(); 195 | 196 | /// 197 | /// @brief Subscribe to a list of instrument tokens. 198 | /// 199 | /// @param instrumentTokens list of instrument tokens that should be 200 | /// subscribed 201 | /// 202 | void subscribe(const std::vector& instrumentTokens); 203 | 204 | /// 205 | /// @brief Unsubscribe. 206 | /// 207 | /// @param instrumentTokens list of instrument tokens that should be 208 | /// unsubscribed 209 | /// 210 | void unsubscribe(const std::vector& instrumentTokens); 211 | 212 | /** 213 | * @brief Set the subscription mode for a list of instrument tokens. 214 | * 215 | * @param mode mode to set 216 | * @param instrumentTokens list of instrument tokens whose mode should be 217 | * set 218 | */ 219 | void setMode(const string& mode, const std::vector& instrumentTokens); 220 | 221 | private: 222 | friend class tickerTest_binaryParsingTest_Test; 223 | const string connectUrlFmt = 224 | "wss://ws.kite.trade/?api_key={0}&access_token={1}"; 225 | string key; 226 | string token; 227 | enum class SEGMENTS : int 228 | { 229 | NSE = 1, 230 | NFO, 231 | CDS, 232 | BSE, 233 | BFO, 234 | BSECDS, 235 | MCX, 236 | MCXSX, 237 | INDICES 238 | }; 239 | enum class MODES 240 | { 241 | LTP, 242 | QUOTE, 243 | FULL 244 | }; 245 | const MODES DEFAULT_MODE = MODES::QUOTE; 246 | std::unordered_map subbedInstruments; 247 | uWS::Hub hub; 248 | // NOLINTNEXTLINE(readability-implicit-bool-conversion) 249 | uWS::Group* group; 250 | // NOLINTNEXTLINE(readability-implicit-bool-conversion) 251 | uWS::WebSocket* ws = nullptr; 252 | static constexpr unsigned int DEFAULT_CONNECT_TIMEOUT = 5; // s 253 | static constexpr unsigned int DEFAULT_MAX_RECONNECT_DELAY = 60; // s 254 | static constexpr unsigned int DEFAULT_MAX_RECONNECT_TRIES = 30; 255 | const unsigned int connectTimeout = DEFAULT_CONNECT_TIMEOUT; // ms 256 | const string pingMessage; 257 | const unsigned int pingInterval = 3000; // ms 258 | const bool enableReconnect = false; 259 | const unsigned int initReconnectDelay = 2; // s 260 | unsigned int reconnectDelay = initReconnectDelay; 261 | const unsigned int maxReconnectDelay = DEFAULT_MAX_RECONNECT_DELAY; // s 262 | unsigned int reconnectTries = 0; 263 | const unsigned int maxReconnectTries = DEFAULT_MAX_RECONNECT_TRIES; 264 | std::atomic isReconnecting { false }; 265 | std::chrono::time_point lastPongTime; 266 | std::chrono::time_point lastBeatTime; 267 | 268 | void connectInternal(); 269 | 270 | void reconnect(); 271 | 272 | void processTextMessage(const string& message); 273 | 274 | template 275 | T unpack(const std::vector& bytes, size_t start, size_t end); 276 | 277 | std::vector> splitPackets(const std::vector& bytes); 278 | 279 | std::vector parseBinaryMessage(char* bytes, size_t size); 280 | 281 | void resubInstruments(); 282 | 283 | void assignCallbacks(); 284 | }; 285 | } // namespace kiteconnect -------------------------------------------------------------------------------- /include/kitepp/responses/market.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2022 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include 30 | 31 | #include "../utils.hpp" 32 | #include "rapidcsv/src/rapidcsv.h" 33 | #include "rapidjson/include/rapidjson/document.h" 34 | #include "rapidjson/include/rapidjson/rapidjson.h" 35 | 36 | namespace kiteconnect { 37 | 38 | using std::string; 39 | namespace rj = rapidjson; 40 | namespace kc = kiteconnect; 41 | namespace utils = kc::internal::utils; 42 | 43 | /// Represents OHLC information of an instrument. 44 | struct ohlc { 45 | ohlc() = default; 46 | explicit ohlc(const rj::Value::Object& val) { parse(val); }; 47 | 48 | void parse(const rj::Value::Object& val) { 49 | open = utils::json::get(val, "open"); 50 | high = utils::json::get(val, "high"); 51 | low = utils::json::get(val, "low"); 52 | close = utils::json::get(val, "close"); 53 | }; 54 | 55 | double open = -1; 56 | double high = -1; 57 | double low = -1; 58 | double close = -1; 59 | }; 60 | 61 | /// Represents market depth of an instrument. 62 | struct depth { 63 | depth() = default; 64 | explicit depth(const rj::Value::Object& val) { parse(val); }; 65 | 66 | void parse(const rj::Value::Object& val) { 67 | price = utils::json::get(val, "price"); 68 | quantity = utils::json::get(val, "quantity"); 69 | orders = utils::json::get(val, "orders"); 70 | }; 71 | 72 | int quantity = -1; 73 | int orders = 0; 74 | double price = -1; 75 | }; 76 | 77 | /// Represents quote informating of an instrument. 78 | struct quote { 79 | quote() = default; 80 | explicit quote(const rj::Value::Object& val) { parse(val); }; 81 | 82 | void parse(const rj::Value::Object& val) { 83 | instrumentToken = utils::json::get(val, "instrument_token"); 84 | timestamp = utils::json::get(val, "timestamp"); 85 | lastPrice = utils::json::get(val, "last_price"); 86 | lastQuantity = utils::json::get(val, "last_quantity"); 87 | lastTradeTime = utils::json::get(val, "last_trade_time"); 88 | averagePrice = utils::json::get(val, "average_price"); 89 | volume = utils::json::get(val, "volume"); 90 | buyQuantity = utils::json::get(val, "buy_quantity"); 91 | sellQuantity = utils::json::get(val, "sell_quantity"); 92 | OHLC = utils::json::get(val, "ohlc"); 93 | netChange = utils::json::get(val, "net_change"); 94 | OI = utils::json::get(val, "oi"); 95 | OIDayHigh = utils::json::get(val, "oi_day_high"); 96 | OIDayLow = utils::json::get(val, "oi_day_low"); 97 | lowerCircuitLimit = 98 | utils::json::get(val, "lower_circuit_limit"); 99 | upperCircuitLimit = 100 | utils::json::get(val, "upper_circuit_limit"); 101 | marketDepth = 102 | utils::json::get(val, "depth"); 103 | }; 104 | 105 | uint32_t instrumentToken = 0; 106 | int64_t volume = -1; 107 | int buyQuantity = -1; 108 | int sellQuantity = -1; 109 | int lastQuantity = -1; 110 | double lastPrice = -1; 111 | double averagePrice = -1; 112 | double netChange = -1; 113 | double OI = -1; 114 | double OIDayHigh = -1; 115 | double OIDayLow = -1; 116 | double lowerCircuitLimit = -1; 117 | double upperCircuitLimit = -1; 118 | string timestamp; 119 | string lastTradeTime; 120 | ohlc OHLC; 121 | struct mDepth { 122 | mDepth() = default; 123 | explicit mDepth(const rj::Value::Object& val) { parse(val); }; 124 | 125 | void parse(const rj::Value::Object& val) { 126 | rj::Value buyDepthVal(rj::kArrayType); 127 | utils::json::get(val, buyDepthVal, "buy"); 128 | for (auto& i : buyDepthVal.GetArray()) { 129 | buy.emplace_back(i.GetObject()); 130 | }; 131 | 132 | rj::Value sellDepthVal(rj::kArrayType); 133 | utils::json::get(val, sellDepthVal, "sell"); 134 | for (auto& i : sellDepthVal.GetArray()) { 135 | sell.emplace_back(i.GetObject()); 136 | }; 137 | } 138 | 139 | std::vector buy; 140 | std::vector sell; 141 | } marketDepth; 142 | }; 143 | 144 | /// Represents a ohlc quote information of an instrument. 145 | struct ohlcQuote { 146 | ohlcQuote() = default; 147 | explicit ohlcQuote(const rj::Value::Object& val) { parse(val); }; 148 | 149 | void parse(const rj::Value::Object& val) { 150 | instrumentToken = utils::json::get(val, "instrument_token"); 151 | lastPrice = utils::json::get(val, "last_price"); 152 | OHLC = utils::json::get(val, "ohlc"); 153 | }; 154 | 155 | uint32_t instrumentToken = 0; 156 | double lastPrice = -1; 157 | ohlc OHLC; 158 | }; 159 | 160 | /// Represents a LTP quote information of an instrument. 161 | struct ltpQuote { 162 | ltpQuote() = default; 163 | explicit ltpQuote(const rj::Value::Object& val) { parse(val); }; 164 | 165 | void parse(const rj::Value::Object& val) { 166 | instrumentToken = utils::json::get(val, "instrument_token"); 167 | lastPrice = utils::json::get(val, "last_price"); 168 | }; 169 | 170 | uint32_t instrumentToken = 0; 171 | double lastPrice = -1; 172 | }; 173 | 174 | /// represents parameters required for the `getHistoricalData` function 175 | struct historicalDataParams { 176 | GENERATE_FLUENT_METHOD( 177 | historicalDataParams, uint32_t, instrumentToken, InstrumentToken); 178 | GENERATE_FLUENT_METHOD(historicalDataParams, bool, continuous, Continuous); 179 | GENERATE_FLUENT_METHOD(historicalDataParams, bool, oi, Oi); 180 | GENERATE_FLUENT_METHOD(historicalDataParams, const string&, from, From); 181 | GENERATE_FLUENT_METHOD(historicalDataParams, const string&, to, To); 182 | GENERATE_FLUENT_METHOD( 183 | historicalDataParams, const string&, interval, Interval); 184 | 185 | uint32_t instrumentToken = 0; 186 | bool continuous = false; 187 | bool oi = false; 188 | string from; 189 | string to; 190 | string interval; 191 | }; 192 | 193 | /// Represents historical data of an instrument. 194 | struct historicalData { 195 | historicalData() = default; 196 | explicit historicalData(const rj::Value::Array& val) { parse(val); }; 197 | 198 | void parse(const rj::Value::Array& val) { 199 | // if the sent value doesn't have a floating point (this time), 200 | // GetDouble() will throw error 201 | static auto getDouble = [](rj::Value& val) -> double { 202 | if (val.IsDouble()) { return val.GetDouble(); }; 203 | if (val.IsInt()) { return val.GetInt(); }; 204 | throw libException("type isn't double"); 205 | }; 206 | datetime = val[DATETIME_IDX].GetString(); 207 | open = getDouble(val[OPEN_IDX]); 208 | high = getDouble(val[HIGH_IDX]); 209 | low = getDouble(val[LOW_IDX]); 210 | close = getDouble(val[CLOSE_IDX]); 211 | volume = val[VOLUME_IDX].GetInt64(); 212 | if (val.Size() > OI_IDX) { OI = val[OI_IDX].GetInt64(); }; 213 | }; 214 | 215 | int64_t volume = -1; 216 | int64_t OI = -1; 217 | double open = -1; 218 | double high = -1; 219 | double low = -1; 220 | double close = -1; 221 | string datetime; 222 | static constexpr uint8_t DATETIME_IDX = 0; 223 | static constexpr uint8_t OPEN_IDX = 1; 224 | static constexpr uint8_t HIGH_IDX = 2; 225 | static constexpr uint8_t LOW_IDX = 3; 226 | static constexpr uint8_t CLOSE_IDX = 4; 227 | static constexpr uint8_t VOLUME_IDX = 5; 228 | static constexpr uint8_t OI_IDX = 6; 229 | }; 230 | 231 | /// Represents information of an instrument. 232 | struct instrument { 233 | instrument() = default; 234 | explicit instrument(const std::vector& row) { parse(row); }; 235 | 236 | void parse(const std::vector& tokens) { 237 | static const auto toInt = [](const string& str) -> int { 238 | return (str.empty()) ? 0 : std::stoi(str); 239 | }; 240 | static const auto toUint32 = [](const string& str) -> uint32_t { 241 | return (str.empty()) ? 0 : std::stoul(str); 242 | }; 243 | static const auto toDouble = [](const string& str) -> double { 244 | return (str.empty()) ? 0.0 : std::stod(str); 245 | }; 246 | 247 | instrumentToken = toUint32(tokens[INSTRUMENT_TOKEN_IDX]); 248 | exchangeToken = toInt(tokens[EXCHANGE_TOKEN_IDX]); 249 | tradingsymbol = tokens[TRADINGSYMBOL_IDX]; 250 | name = tokens[NAME_IDX]; 251 | lastPrice = toDouble(tokens[LAST_PRICE_IDX]); 252 | expiry = tokens[EXPIRY_IDX]; 253 | strikePrice = toDouble(tokens[STRIKE_PRICE_IDX]); 254 | tickSize = toDouble(tokens[TICK_SIZE_IDX]); 255 | lotSize = toDouble(tokens[LOT_SIZE_IDX]); 256 | instrumentType = tokens[INSTRUMENT_TYPE_IDX]; 257 | segment = tokens[SEGMENT_IDX]; 258 | exchange = tokens[EXCHANGE_IDX]; 259 | }; 260 | 261 | uint32_t instrumentToken = 0; 262 | int exchangeToken = -1; 263 | double lastPrice = -1; 264 | double strikePrice = -1; 265 | double tickSize = -1; 266 | double lotSize = -1; 267 | string tradingsymbol; 268 | string name; 269 | string expiry; 270 | string instrumentType; 271 | string segment; 272 | string exchange; 273 | 274 | static constexpr uint8_t INSTRUMENT_TOKEN_IDX = 0; 275 | static constexpr uint8_t EXCHANGE_TOKEN_IDX = 1; 276 | static constexpr uint8_t TRADINGSYMBOL_IDX = 2; 277 | static constexpr uint8_t NAME_IDX = 3; 278 | static constexpr uint8_t LAST_PRICE_IDX = 4; 279 | static constexpr uint8_t EXPIRY_IDX = 5; 280 | static constexpr uint8_t STRIKE_PRICE_IDX = 6; 281 | static constexpr uint8_t TICK_SIZE_IDX = 7; 282 | static constexpr uint8_t LOT_SIZE_IDX = 8; 283 | static constexpr uint8_t INSTRUMENT_TYPE_IDX = 9; 284 | static constexpr uint8_t SEGMENT_IDX = 10; 285 | static constexpr uint8_t EXCHANGE_IDX = 11; 286 | }; 287 | 288 | } // namespace kiteconnect -------------------------------------------------------------------------------- /tests/unit/kite/gtt.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2022 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include "../kitepp.hpp" 37 | #include "../utils.hpp" 38 | 39 | using std::string; 40 | using ::testing::ByMove; 41 | using ::testing::Return; 42 | using ::testing::StrictMock; 43 | namespace kc = kiteconnect; 44 | namespace utils = kc::internal::utils; 45 | 46 | TEST(kiteTest, placeGttTest) { 47 | const string JSON = 48 | kc::test::readFile("../tests/mock_responses/gtt_place_order.json"); 49 | constexpr double LAST_PRICE = 798.0; 50 | const string TRIGGER_TYPE = "single"; 51 | const string SYMBOL = "INFY"; 52 | const string EXCHANGE = "NSE"; 53 | const std::vector TRIGGER_VALUES = { 702.0 }; 54 | constexpr int GTT_PARAM1_QUANTITY = 1; 55 | constexpr double GTT_PARAM1_PRICE = 702.5; 56 | const string GTT_PARAM1_TRANSACTON_TYPE = "BUY"; 57 | const string GTT_PARAM1_ORDER_TYPE = "LIMIT"; 58 | const string GTT_PARAM1_PRODUCT = "CNC"; 59 | constexpr int EXPECTED_TRIGGER_ID = 123; 60 | StrictMock Kite; 61 | EXPECT_CALL(Kite, 62 | sendReq(utils::http::endpoint { utils::http::METHOD::POST, 63 | "/gtt/triggers" }, 64 | utils::http::Params { 65 | { "type", "single" }, 66 | { "condition", 67 | R"({"exchange":"NSE","tradingsymbol":"INFY","trigger_values":[702.0],"last_price":798.0})" }, 68 | { "orders", 69 | R"([{"exchange":"NSE","tradingsymbol":"INFY","transaction_type":"BUY","quantity":1,"order_type":"LIMIT","product":"CNC","price":702.5}])" }, 70 | }, 71 | utils::FmtArgs {})) 72 | .Times(1) 73 | .WillOnce( 74 | Return(ByMove(utils::http::response(utils::http::code::OK, JSON)))); 75 | 76 | // clang-format off 77 | const int TRIGGER_ID = Kite.placeGtt(kc::placeGttParams() 78 | .LastPrice(LAST_PRICE) 79 | .TriggerType(TRIGGER_TYPE) 80 | .Symbol(SYMBOL) 81 | .Exchange(EXCHANGE) 82 | .TriggerValues(TRIGGER_VALUES) 83 | .GttParamsList({ 84 | kc::gttParams() 85 | .Quantity(GTT_PARAM1_QUANTITY) 86 | .Price(GTT_PARAM1_PRICE) 87 | .TransactionType(GTT_PARAM1_TRANSACTON_TYPE) 88 | .OrderType(GTT_PARAM1_ORDER_TYPE) 89 | .Product(GTT_PARAM1_PRODUCT) 90 | })); 91 | // clang-format on 92 | 93 | EXPECT_EQ(TRIGGER_ID, EXPECTED_TRIGGER_ID); 94 | } 95 | 96 | TEST(kiteTest, getGTTsTest) { 97 | const string JSON = 98 | kc::test::readFile("../tests/mock_responses/gtt_get_orders.json"); 99 | StrictMock Kite; 100 | EXPECT_CALL(Kite, sendReq(utils::http::endpoint { utils::http::METHOD::GET, 101 | "/gtt/triggers" }, 102 | utils::http::Params {}, utils::FmtArgs {})) 103 | .Times(1) 104 | .WillOnce( 105 | Return(ByMove(utils::http::response(utils::http::code::OK, JSON)))); 106 | 107 | const std::vector Triggers = Kite.triggers(); 108 | 109 | ASSERT_EQ(Triggers.size(), 2); 110 | kc::GTT order1 = Triggers[0]; 111 | EXPECT_EQ(order1.ID, 112127); 112 | EXPECT_EQ(order1.userID, "XX0000"); 113 | EXPECT_EQ(order1.type, "single"); 114 | EXPECT_EQ(order1.createdAt, "2019-09-12 13:25:16"); 115 | EXPECT_EQ(order1.updatedAt, "2019-09-12 13:25:16"); 116 | EXPECT_EQ(order1.expiresAt, "2020-09-12 13:25:16"); 117 | EXPECT_EQ(order1.status, "active"); 118 | EXPECT_EQ(order1.condition.exchange, "NSE"); 119 | EXPECT_DOUBLE_EQ(order1.condition.lastPrice, 798); 120 | EXPECT_EQ(order1.condition.tradingsymbol, "INFY"); 121 | EXPECT_DOUBLE_EQ(order1.condition.triggerValues[0], 702); 122 | EXPECT_EQ(order1.orders[0].exchange, "NSE"); 123 | EXPECT_EQ(order1.orders[0].tradingsymbol, "INFY"); 124 | EXPECT_EQ(order1.orders[0].product, "CNC"); 125 | EXPECT_EQ(order1.orders[0].orderType, "LIMIT"); 126 | EXPECT_EQ(order1.orders[0].transactionType, "BUY"); 127 | EXPECT_EQ(order1.orders[0].quantity, 1); 128 | EXPECT_DOUBLE_EQ(order1.orders[0].price, 702.5); 129 | 130 | kc::GTT order2 = Triggers[1]; 131 | EXPECT_EQ(order2.ID, 105099); 132 | EXPECT_EQ(order2.userID, "XX0000"); 133 | EXPECT_EQ(order2.type, "two-leg"); 134 | EXPECT_EQ(order2.createdAt, "2019-09-09 15:13:22"); 135 | EXPECT_EQ(order2.updatedAt, "2019-09-09 15:15:08"); 136 | EXPECT_EQ(order2.expiresAt, "2020-01-01 12:00:00"); 137 | EXPECT_EQ(order2.status, "triggered"); 138 | EXPECT_EQ(order2.condition.exchange, "NSE"); 139 | EXPECT_DOUBLE_EQ(order2.condition.lastPrice, 102.6); 140 | EXPECT_EQ(order2.condition.tradingsymbol, "RAIN"); 141 | EXPECT_THAT( 142 | order2.condition.triggerValues, ::testing::ElementsAre(102.0, 103.7)); 143 | EXPECT_EQ(order2.orders[0].tradingsymbol, "RAIN"); 144 | EXPECT_EQ(order2.orders[0].product, "CNC"); 145 | EXPECT_EQ(order2.orders[0].orderType, "LIMIT"); 146 | EXPECT_EQ(order2.orders[0].transactionType, "SELL"); 147 | EXPECT_EQ(order2.orders[0].quantity, 1); 148 | EXPECT_DOUBLE_EQ(order2.orders[0].price, 1); 149 | EXPECT_EQ(order2.orders[1].tradingsymbol, "RAIN"); 150 | EXPECT_EQ(order2.orders[1].product, "CNC"); 151 | EXPECT_EQ(order2.orders[1].orderType, "LIMIT"); 152 | EXPECT_EQ(order2.orders[1].transactionType, "SELL"); 153 | EXPECT_EQ(order2.orders[1].quantity, 1); 154 | EXPECT_DOUBLE_EQ(order2.orders[1].price, 1); 155 | } 156 | 157 | TEST(kiteTest, getGTTTest) { 158 | const string JSON = 159 | kc::test::readFile("../tests/mock_responses/gtt_get_order.json"); 160 | constexpr int TRIGGER_ID = 123; 161 | StrictMock Kite; 162 | EXPECT_CALL(Kite, sendReq(utils::http::endpoint { utils::http::METHOD::GET, 163 | "/gtt/triggers/{0}" }, 164 | utils::http::Params {}, 165 | utils::FmtArgs { std::to_string(TRIGGER_ID) })) 166 | .Times(1) 167 | .WillOnce( 168 | Return(ByMove(utils::http::response(utils::http::code::OK, JSON)))); 169 | 170 | const kc::GTT trigger = Kite.getGtt(TRIGGER_ID); 171 | EXPECT_EQ(trigger.ID, 123); 172 | EXPECT_EQ(trigger.userID, "XX0000"); 173 | EXPECT_EQ(trigger.type, "two-leg"); 174 | EXPECT_EQ(trigger.createdAt, "2019-09-09 15:13:22"); 175 | EXPECT_EQ(trigger.updatedAt, "2019-09-09 15:15:08"); 176 | EXPECT_EQ(trigger.expiresAt, "2020-01-01 12:00:00"); 177 | EXPECT_EQ(trigger.status, "triggered"); 178 | EXPECT_EQ(trigger.condition.exchange, "NSE"); 179 | EXPECT_DOUBLE_EQ(trigger.condition.lastPrice, 102.6); 180 | EXPECT_EQ(trigger.condition.tradingsymbol, "RAIN"); 181 | EXPECT_THAT( 182 | trigger.condition.triggerValues, ::testing::ElementsAre(102.0, 103.7)); 183 | EXPECT_EQ(trigger.orders[0].tradingsymbol, "RAIN"); 184 | EXPECT_EQ(trigger.orders[0].product, "CNC"); 185 | EXPECT_EQ(trigger.orders[0].orderType, "LIMIT"); 186 | EXPECT_EQ(trigger.orders[0].transactionType, "SELL"); 187 | EXPECT_EQ(trigger.orders[0].quantity, 1); 188 | EXPECT_DOUBLE_EQ(trigger.orders[0].price, 1); 189 | } 190 | 191 | TEST(kiteTest, modifyGttTest) { 192 | const string JSON = 193 | kc::test::readFile("../tests/mock_responses/gtt_modify_order.json"); 194 | constexpr double LAST_PRICE = 798.0; 195 | const string TRIGGER_TYPE = "single"; 196 | const string SYMBOL = "INFY"; 197 | const string EXCHANGE = "NSE"; 198 | const std::vector TRIGGER_VALUES = { 702.0 }; 199 | constexpr int GTT_PARAM1_QUANTITY = 2; 200 | constexpr double GTT_PARAM1_PRICE = 702.5; 201 | const string GTT_PARAM1_TRANSACTON_TYPE = "BUY"; 202 | const string GTT_PARAM1_ORDER_TYPE = "LIMIT"; 203 | const string GTT_PARAM1_PRODUCT = "CNC"; 204 | constexpr int TRIGGER_ID = 123; 205 | constexpr int EXPECTED_TRIGGER_ID = 123; 206 | StrictMock Kite; 207 | EXPECT_CALL(Kite, 208 | sendReq(utils::http::endpoint { utils::http::METHOD::PUT, 209 | "/gtt/triggers/{0}" }, 210 | utils::http::Params { 211 | { "type", "single" }, 212 | { "condition", 213 | R"({"exchange":"NSE","tradingsymbol":"INFY","trigger_values":[702.0],"last_price":798.0})" }, 214 | { "orders", 215 | R"([{"exchange":"NSE","tradingsymbol":"INFY","transaction_type":"BUY","quantity":2,"order_type":"LIMIT","product":"CNC","price":702.5}])" }, 216 | }, 217 | utils::FmtArgs { std::to_string(TRIGGER_ID) })) 218 | .Times(1) 219 | .WillOnce( 220 | Return(ByMove(utils::http::response(utils::http::code::OK, JSON)))); 221 | 222 | const int RECEIVED_TRIGGER_ID = Kite.modifyGtt( 223 | kc::modifyGttParams() 224 | .TriggerId(TRIGGER_ID) 225 | .LastPrice(LAST_PRICE) 226 | .TriggerType(TRIGGER_TYPE) 227 | .Symbol(SYMBOL) 228 | .Exchange(EXCHANGE) 229 | .TriggerValues(TRIGGER_VALUES) 230 | .GttParamsList({ kc::gttParams() 231 | .Quantity(GTT_PARAM1_QUANTITY) 232 | .Price(GTT_PARAM1_PRICE) 233 | .TransactionType(GTT_PARAM1_TRANSACTON_TYPE) 234 | .OrderType(GTT_PARAM1_ORDER_TYPE) 235 | .Product(GTT_PARAM1_PRODUCT) })); 236 | 237 | EXPECT_EQ(RECEIVED_TRIGGER_ID, EXPECTED_TRIGGER_ID); 238 | } 239 | 240 | TEST(kiteTest, deleteGTTTest) { 241 | const string JSON = 242 | kc::test::readFile("../tests/mock_responses/gtt_delete_order.json"); 243 | constexpr int TRIGGER_ID = 123; 244 | constexpr int EXPECTED_TRIGGER_ID = 123; 245 | StrictMock Kite; 246 | EXPECT_CALL(Kite, sendReq(utils::http::endpoint { utils::http::METHOD::DEL, 247 | "/gtt/triggers/{0}" }, 248 | utils::http::Params {}, 249 | utils::FmtArgs { std::to_string(TRIGGER_ID) })) 250 | .Times(1) 251 | .WillOnce( 252 | Return(ByMove(utils::http::response(utils::http::code::OK, JSON)))); 253 | 254 | const int RECEIVED_TRIGGER_ID = Kite.deleteGtt(TRIGGER_ID); 255 | 256 | EXPECT_EQ(RECEIVED_TRIGGER_ID, EXPECTED_TRIGGER_ID); 257 | } 258 | -------------------------------------------------------------------------------- /tests/unit/kite/margins.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the MIT License . 3 | * SPDX-License-Identifier: MIT 4 | * 5 | * Copyright (c) 2020-2023 Bhumit Attarde 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 20 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 22 | * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include "../kitepp.hpp" 37 | #include "../utils.hpp" 38 | 39 | using std::string; 40 | using ::testing::ByMove; 41 | using ::testing::Return; 42 | using ::testing::StrictMock; 43 | namespace kc = kiteconnect; 44 | namespace utils = kc::internal::utils; 45 | 46 | TEST(kiteTest, getOrderMarginsTest) { 47 | const string JSON = 48 | kc::test::readFile("../tests/mock_responses/order_margins.json"); 49 | constexpr double QUANTITY = 1; 50 | constexpr double PRICE = 0; 51 | constexpr double TRIGGER_PRICE = 0; 52 | const string EXCHANGE = "NSE"; 53 | const string TRADINGSYMBOL = "INFY"; 54 | const string TRANSACTION_TYPE = "BUY"; 55 | const string VARIETY = "regular"; 56 | const string PRODUCT = "CNC"; 57 | const string ORDER_TYPE = "MARKET"; 58 | 59 | StrictMock Kite; 60 | EXPECT_CALL(Kite, 61 | sendReq(utils::http::endpoint { utils::http::METHOD::POST, 62 | "/margins/orders", utils::http::CONTENT_TYPE::JSON }, 63 | utils::http::Params { { "", 64 | R"([{"exchange":"NSE","tradingsymbol":"INFY","transaction_type":"BUY","variety":"regular","product":"CNC","order_type":"MARKET","quantity":1.0,"price":0.0,"trigger_price":0.0}])" } }, 65 | utils::FmtArgs {})) 66 | .Times(1) 67 | .WillOnce( 68 | Return(ByMove(utils::http::response(utils::http::code::OK, JSON)))); 69 | 70 | const std::vector MARGINS = 71 | Kite.getOrderMargins({ kc::marginsParams() 72 | .Quantity(QUANTITY) 73 | .Price(PRICE) 74 | .TriggerPrice(TRIGGER_PRICE) 75 | .Exchange(EXCHANGE) 76 | .Tradingsymbol(TRADINGSYMBOL) 77 | .TransactionType(TRANSACTION_TYPE) 78 | .Variety(VARIETY) 79 | .Product(PRODUCT) 80 | .OrderType(ORDER_TYPE) }); 81 | 82 | ASSERT_EQ(MARGINS.size(), 1); 83 | kc::orderMargins ordMargins1 = MARGINS[0]; 84 | EXPECT_EQ(ordMargins1.type, "equity"); 85 | EXPECT_EQ(ordMargins1.tradingSymbol, "INFY"); 86 | EXPECT_EQ(ordMargins1.exchange, "NSE"); 87 | EXPECT_DOUBLE_EQ(ordMargins1.span, 0); 88 | EXPECT_DOUBLE_EQ(ordMargins1.exposure, 0); 89 | EXPECT_DOUBLE_EQ(ordMargins1.optionPremium, 0); 90 | EXPECT_DOUBLE_EQ(ordMargins1.additional, 0); 91 | EXPECT_DOUBLE_EQ(ordMargins1.bo, 0); 92 | EXPECT_DOUBLE_EQ(ordMargins1.cash, 0); 93 | EXPECT_DOUBLE_EQ(ordMargins1.var, 1498); 94 | EXPECT_DOUBLE_EQ(ordMargins1.pnl.realised, 0); 95 | EXPECT_DOUBLE_EQ(ordMargins1.pnl.unrealised, 0); 96 | EXPECT_DOUBLE_EQ(ordMargins1.total, 1498); 97 | EXPECT_DOUBLE_EQ(ordMargins1.leverage, 1); 98 | 99 | EXPECT_DOUBLE_EQ(ordMargins1.charges.transactionTax, 1.498); 100 | EXPECT_EQ(ordMargins1.charges.transactionTaxType, "stt"); 101 | EXPECT_DOUBLE_EQ(ordMargins1.charges.exchangeTurnoverCharge, 0.051681); 102 | EXPECT_DOUBLE_EQ(ordMargins1.charges.sebiTurnoverCharge, 0.001498); 103 | EXPECT_DOUBLE_EQ(ordMargins1.charges.brokerage, 0.01); 104 | EXPECT_DOUBLE_EQ(ordMargins1.charges.stampDuty, 0.22); 105 | 106 | EXPECT_DOUBLE_EQ(ordMargins1.charges.gst.igst, 0.011372219999999999); 107 | EXPECT_DOUBLE_EQ(ordMargins1.charges.gst.cgst, 0); 108 | EXPECT_DOUBLE_EQ(ordMargins1.charges.gst.sgst, 0); 109 | EXPECT_DOUBLE_EQ(ordMargins1.charges.gst.total, 0.011372219999999999); 110 | } 111 | 112 | TEST(kiteTest, getBasketMarginsTest) { 113 | const string JSON = 114 | kc::test::readFile("../tests/mock_responses/basket_margins.json"); 115 | constexpr double QUANTITY = 1; 116 | constexpr double PRICE = 0; 117 | constexpr double TRIGGER_PRICE = 0; 118 | const string EXCHANGE = "NSE"; 119 | const string TRADINGSYMBOL = "INFY"; 120 | const string TRANSACTION_TYPE = "BUY"; 121 | const string VARIETY = "regular"; 122 | const string PRODUCT = "CNC"; 123 | const string ORDER_TYPE = "MARKET"; 124 | const bool CONSIDER_POSITIONS = false; 125 | 126 | StrictMock Kite; 127 | EXPECT_CALL(Kite, 128 | sendReq(utils::http::endpoint { utils::http::METHOD::POST, 129 | "/margins/basket?consider_positions={0}", 130 | utils::http::CONTENT_TYPE::JSON }, 131 | utils::http::Params { { "", 132 | R"([{"exchange":"NSE","tradingsymbol":"INFY","transaction_type":"BUY","variety":"regular","product":"CNC","order_type":"MARKET","quantity":1.0,"price":0.0,"trigger_price":0.0}])" } }, 133 | utils::FmtArgs { CONSIDER_POSITIONS ? "true" : "false" })) 134 | .Times(1) 135 | .WillOnce( 136 | Return(ByMove(utils::http::response(utils::http::code::OK, JSON)))); 137 | 138 | const kc::basketMargins MARGINS = 139 | Kite.getBasketMargins({ kc::marginsParams() 140 | .Quantity(QUANTITY) 141 | .Price(PRICE) 142 | .TriggerPrice(TRIGGER_PRICE) 143 | .Exchange(EXCHANGE) 144 | .Tradingsymbol(TRADINGSYMBOL) 145 | .TransactionType(TRANSACTION_TYPE) 146 | .Variety(VARIETY) 147 | .Product(PRODUCT) 148 | .OrderType(ORDER_TYPE) }, 149 | CONSIDER_POSITIONS); 150 | 151 | ASSERT_EQ(MARGINS.initial.type, ""); 152 | ASSERT_EQ(MARGINS.initial.tradingSymbol, ""); 153 | ASSERT_EQ(MARGINS.initial.exchange, ""); 154 | EXPECT_DOUBLE_EQ(MARGINS.initial.span, 132257.58); 155 | EXPECT_DOUBLE_EQ(MARGINS.initial.exposure, 56597.19); 156 | EXPECT_DOUBLE_EQ(MARGINS.initial.optionPremium, 0); 157 | EXPECT_DOUBLE_EQ(MARGINS.initial.additional, 0); 158 | EXPECT_DOUBLE_EQ(MARGINS.initial.bo, 0); 159 | EXPECT_DOUBLE_EQ(MARGINS.initial.cash, 0); 160 | EXPECT_DOUBLE_EQ(MARGINS.initial.var, 0); 161 | EXPECT_DOUBLE_EQ(MARGINS.initial.pnl.realised, 0); 162 | EXPECT_DOUBLE_EQ(MARGINS.initial.pnl.unrealised, 0); 163 | EXPECT_DOUBLE_EQ(MARGINS.initial.leverage, 0); 164 | 165 | EXPECT_DOUBLE_EQ(MARGINS.initial.charges.transactionTax, 0); 166 | ASSERT_EQ(MARGINS.initial.charges.transactionTaxType, ""); 167 | EXPECT_DOUBLE_EQ(MARGINS.initial.charges.exchangeTurnoverCharge, 0); 168 | EXPECT_DOUBLE_EQ(MARGINS.initial.charges.sebiTurnoverCharge, 0); 169 | EXPECT_DOUBLE_EQ(MARGINS.initial.charges.brokerage, 0); 170 | EXPECT_DOUBLE_EQ(MARGINS.initial.charges.stampDuty, 0); 171 | 172 | EXPECT_DOUBLE_EQ(MARGINS.initial.charges.gst.igst, 0); 173 | EXPECT_DOUBLE_EQ(MARGINS.initial.charges.gst.cgst, 0); 174 | EXPECT_DOUBLE_EQ(MARGINS.initial.charges.gst.sgst, 0); 175 | EXPECT_DOUBLE_EQ(MARGINS.initial.charges.gst.total, 0); 176 | EXPECT_DOUBLE_EQ(MARGINS.initial.charges.total, 0); 177 | EXPECT_DOUBLE_EQ(MARGINS.initial.total, 188854.77); 178 | 179 | ASSERT_EQ(MARGINS.final.type, ""); 180 | ASSERT_EQ(MARGINS.final.tradingSymbol, ""); 181 | ASSERT_EQ(MARGINS.final.exchange, ""); 182 | EXPECT_DOUBLE_EQ(MARGINS.final.span, 26000.519999999986); 183 | EXPECT_DOUBLE_EQ(MARGINS.final.exposure, 9452.689999999999); 184 | EXPECT_DOUBLE_EQ(MARGINS.final.optionPremium, 0); 185 | EXPECT_DOUBLE_EQ(MARGINS.final.additional, 0); 186 | EXPECT_DOUBLE_EQ(MARGINS.final.bo, 0); 187 | EXPECT_DOUBLE_EQ(MARGINS.final.cash, 0); 188 | EXPECT_DOUBLE_EQ(MARGINS.final.var, 0); 189 | EXPECT_DOUBLE_EQ(MARGINS.final.pnl.realised, 0); 190 | EXPECT_DOUBLE_EQ(MARGINS.final.pnl.unrealised, 0); 191 | EXPECT_DOUBLE_EQ(MARGINS.final.leverage, 0); 192 | 193 | EXPECT_DOUBLE_EQ(MARGINS.final.charges.transactionTax, 0); 194 | ASSERT_EQ(MARGINS.final.charges.transactionTaxType, ""); 195 | EXPECT_DOUBLE_EQ(MARGINS.final.charges.exchangeTurnoverCharge, 0); 196 | EXPECT_DOUBLE_EQ(MARGINS.final.charges.sebiTurnoverCharge, 0); 197 | EXPECT_DOUBLE_EQ(MARGINS.final.charges.brokerage, 0); 198 | EXPECT_DOUBLE_EQ(MARGINS.final.charges.stampDuty, 0); 199 | 200 | EXPECT_DOUBLE_EQ(MARGINS.final.charges.gst.igst, 0); 201 | EXPECT_DOUBLE_EQ(MARGINS.final.charges.gst.cgst, 0); 202 | EXPECT_DOUBLE_EQ(MARGINS.final.charges.gst.sgst, 0); 203 | EXPECT_DOUBLE_EQ(MARGINS.final.charges.gst.total, 0); 204 | 205 | EXPECT_DOUBLE_EQ(MARGINS.final.charges.total, 0); 206 | EXPECT_DOUBLE_EQ(MARGINS.final.total, 35453.209999999985); 207 | 208 | ASSERT_EQ(MARGINS.orders.size(), 2); 209 | 210 | kc::orderMargins order1 = MARGINS.orders[0]; 211 | EXPECT_EQ(order1.type, "equity"); 212 | EXPECT_EQ(order1.tradingSymbol, "NIFTY23JANFUT"); 213 | EXPECT_EQ(order1.exchange, "NFO"); 214 | EXPECT_DOUBLE_EQ(order1.span, 132257.58); 215 | EXPECT_DOUBLE_EQ(order1.exposure, 28239.120000000003); 216 | EXPECT_DOUBLE_EQ(order1.optionPremium, 0); 217 | EXPECT_DOUBLE_EQ(order1.additional, 0); 218 | EXPECT_DOUBLE_EQ(order1.bo, 0); 219 | EXPECT_DOUBLE_EQ(order1.cash, 0); 220 | EXPECT_DOUBLE_EQ(order1.var, 0); 221 | EXPECT_DOUBLE_EQ(order1.pnl.realised, 0); 222 | EXPECT_DOUBLE_EQ(order1.pnl.unrealised, 0); 223 | EXPECT_DOUBLE_EQ(order1.leverage, 1); 224 | 225 | EXPECT_DOUBLE_EQ(order1.charges.transactionTax, 0); 226 | ASSERT_EQ(order1.charges.transactionTaxType, ""); 227 | EXPECT_DOUBLE_EQ(order1.charges.exchangeTurnoverCharge, 0); 228 | EXPECT_DOUBLE_EQ(order1.charges.sebiTurnoverCharge, 0); 229 | EXPECT_DOUBLE_EQ(order1.charges.brokerage, 0); 230 | EXPECT_DOUBLE_EQ(order1.charges.stampDuty, 0); 231 | 232 | EXPECT_DOUBLE_EQ(order1.charges.gst.igst, 0); 233 | EXPECT_DOUBLE_EQ(order1.charges.gst.cgst, 0); 234 | EXPECT_DOUBLE_EQ(order1.charges.gst.sgst, 0); 235 | EXPECT_DOUBLE_EQ(order1.charges.gst.total, 0); 236 | 237 | EXPECT_DOUBLE_EQ(order1.charges.total, 0); 238 | EXPECT_DOUBLE_EQ(order1.total, 160496.69999999998); 239 | 240 | kc::orderMargins order2 = MARGINS.orders[1]; 241 | EXPECT_EQ(order2.type, "equity"); 242 | EXPECT_EQ(order2.tradingSymbol, "NIFTY23FEBFUT"); 243 | EXPECT_EQ(order2.exchange, "NFO"); 244 | EXPECT_DOUBLE_EQ(order2.span, 0); 245 | EXPECT_DOUBLE_EQ(order2.exposure, 28358.07); 246 | EXPECT_DOUBLE_EQ(order2.optionPremium, 0); 247 | EXPECT_DOUBLE_EQ(order2.additional, 0); 248 | EXPECT_DOUBLE_EQ(order2.bo, 0); 249 | EXPECT_DOUBLE_EQ(order2.cash, 0); 250 | EXPECT_DOUBLE_EQ(order2.var, 0); 251 | EXPECT_DOUBLE_EQ(order2.pnl.realised, 0); 252 | EXPECT_DOUBLE_EQ(order2.pnl.unrealised, 0); 253 | EXPECT_DOUBLE_EQ(order2.leverage, 1); 254 | 255 | EXPECT_DOUBLE_EQ(order2.charges.transactionTax, 0); 256 | ASSERT_EQ(order2.charges.transactionTaxType, ""); 257 | EXPECT_DOUBLE_EQ(order2.charges.exchangeTurnoverCharge, 0); 258 | EXPECT_DOUBLE_EQ(order2.charges.sebiTurnoverCharge, 0); 259 | EXPECT_DOUBLE_EQ(order2.charges.brokerage, 0); 260 | EXPECT_DOUBLE_EQ(order2.charges.stampDuty, 0); 261 | 262 | EXPECT_DOUBLE_EQ(order2.charges.gst.igst, 0); 263 | EXPECT_DOUBLE_EQ(order2.charges.gst.cgst, 0); 264 | EXPECT_DOUBLE_EQ(order2.charges.gst.sgst, 0); 265 | EXPECT_DOUBLE_EQ(order2.charges.gst.total, 0); 266 | 267 | EXPECT_DOUBLE_EQ(order2.charges.total, 0); 268 | EXPECT_DOUBLE_EQ(order2.total, 28358.07); 269 | } --------------------------------------------------------------------------------