tksbrokerapi.TradeRoutines
This library contains some methods used by trade scenarios implemented with TKSBrokerAPI module.
- TKSBrokerAPI module documentation: https://tim55667757.github.io/TKSBrokerAPI/docs/tksbrokerapi/TKSBrokerAPI.html
- TKSBrokerAPI CLI examples: https://github.com/Tim55667757/TKSBrokerAPI/blob/master/README_EN.md
- About Tinkoff Invest API: https://tinkoff.github.io/investAPI/
- Tinkoff Invest API documentation: https://tinkoff.github.io/investAPI/swagger-ui/
- Open account for trading: http://tinkoff.ru/sl/AaX1Et1omnH
1# -*- coding: utf-8 -*- 2# Author: Timur Gilmullin 3 4""" 5This library contains some methods used by trade scenarios implemented with TKSBrokerAPI module. 6 7- **TKSBrokerAPI module documentation:** https://tim55667757.github.io/TKSBrokerAPI/docs/tksbrokerapi/TKSBrokerAPI.html 8- **TKSBrokerAPI CLI examples:** https://github.com/Tim55667757/TKSBrokerAPI/blob/master/README_EN.md 9- **About Tinkoff Invest API:** https://tinkoff.github.io/investAPI/ 10- **Tinkoff Invest API documentation:** https://tinkoff.github.io/investAPI/swagger-ui/ 11- **Open account for trading:** http://tinkoff.ru/sl/AaX1Et1omnH 12""" 13 14# Copyright (c) 2022 Gilmillin Timur Mansurovich 15# 16# Licensed under the Apache License, Version 2.0 (the "License"); 17# you may not use this file except in compliance with the License. 18# You may obtain a copy of the License at 19# 20# http://www.apache.org/licenses/LICENSE-2.0 21# 22# Unless required by applicable law or agreed to in writing, software 23# distributed under the License is distributed on an "AS IS" BASIS, 24# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 25# See the License for the specific language governing permissions and 26# limitations under the License. 27 28 29from datetime import datetime, timedelta 30from dateutil.tz import tzutc 31 32 33# --- Main constants: 34 35NANO = 0.000000001 # SI-constant nano = 10^-9 36 37 38def GetDatesAsString(start: str = None, end: str = None, userFormat: str = "%Y-%m-%d", outputFormat: str = "%Y-%m-%dT%H:%M:%SZ") -> tuple[str, str]: 39 """ 40 Create tuple of date and time strings with timezone parsed from user-friendly date. 41 42 Warning! All dates must be in UTC time zone! 43 44 User dates format must be like: `"%Y-%m-%d"`, e.g. `"2020-02-03"` (3 Feb, 2020). 45 46 Output date is UTC ISO time format by default: `"%Y-%m-%dT%H:%M:%SZ"`. 47 48 Example input: `start="2022-06-01", end="2022-06-20"` -> output: `("2022-06-01T00:00:00Z", "2022-06-20T23:59:59Z")`. 49 An error exception will occur if input date has incorrect format. 50 51 If `start=None`, `end=None` then return dates from yesterday to the end of the day. 52 53 If `start=some_date_1`, `end=None` then return dates from `some_date_1` to the end of the day. 54 55 If `start=some_date_1`, `end=some_date_2` then return dates from start of `some_date_1` to end of `some_date_2`. 56 57 Start day may be negative integer numbers: `-1`, `-2`, `-3` — how many days ago. 58 59 Also, you can use keywords for start if `end=None`: 60 - `today` (from 00:00:00 to the end of current day), 61 - `yesterday` (-1 day from 00:00:00 to 23:59:59), 62 - `week` (-7 day from 00:00:00 to the end of current day), 63 - `month` (-30 day from 00:00:00 to the end of current day), 64 - `year` (-365 day from 00:00:00 to the end of current day), 65 66 :param start: start day in format defined by `userFormat` or keyword. 67 :param end: end day in format defined by `userFormat`. 68 :param userFormat: user-friendly date format, e.g. `"%Y-%m-%d"`. 69 :param outputFormat: output string date format. 70 :return: tuple with 2 strings `("start", "end")`. Example of return is `("2022-06-01T00:00:00Z", "2022-06-20T23:59:59Z")`. 71 Second string is the end of the last day. 72 """ 73 s = datetime.now(tzutc()).replace(hour=0, minute=0, second=0, microsecond=0) # start of the current day 74 e = s.replace(hour=23, minute=59, second=59, microsecond=0) # end of the current day 75 76 # time between start and the end of the current day: 77 if start is None or start.lower() == "today": 78 pass 79 80 # from start of the last day to the end of the last day: 81 elif start.lower() == "yesterday": 82 s -= timedelta(days=1) 83 e -= timedelta(days=1) 84 85 # week (-7 day from 00:00:00 to the end of the current day): 86 elif start.lower() == "week": 87 s -= timedelta(days=6) # +1 current day already taken into account 88 89 # month (-30 day from 00:00:00 to the end of current day): 90 elif start.lower() == "month": 91 s -= timedelta(days=29) # +1 current day already taken into account 92 93 # year (-365 day from 00:00:00 to the end of current day): 94 elif start.lower() == "year": 95 s -= timedelta(days=364) # +1 current day already taken into account 96 97 # -N days ago to the end of current day: 98 elif start.startswith('-') and start[1:].isdigit(): 99 s -= timedelta(days=abs(int(start)) - 1) # +1 current day already taken into account 100 101 # dates between start day at 00:00:00 and the end of the last day at 23:59:59: 102 else: 103 s = datetime.strptime(start, userFormat).replace(hour=0, minute=0, second=0, microsecond=0, tzinfo=tzutc()) 104 e = datetime.strptime(end, userFormat).replace(hour=23, minute=59, second=59, microsecond=0, tzinfo=tzutc()) if end is not None else e 105 106 # converting to UTC ISO time formatted with Z suffix for Tinkoff Open API: 107 s = s.strftime(outputFormat) 108 e = e.strftime(outputFormat) 109 110 return s, e 111 112 113def NanoToFloat(units: str, nano: int) -> float: 114 """ 115 Convert number in nano-view mode with string parameter `units` and integer parameter `nano` to float view. Examples: 116 117 `NanoToFloat(units="2", nano=500000000) -> 2.5` 118 119 `NanoToFloat(units="0", nano=50000000) -> 0.05` 120 121 :param units: integer string or integer parameter that represents the integer part of number 122 :param nano: integer string or integer parameter that represents the fractional part of number 123 :return: float view of number 124 """ 125 return int(units) + int(nano) * NANO 126 127 128def FloatToNano(number: float) -> dict: 129 """ 130 Convert float number to nano-type view: dictionary with string `units` and integer `nano` parameters `{"units": "string", "nano": integer}`. Examples: 131 132 `FloatToNano(number=2.5) -> {"units": "2", "nano": 500000000}` 133 134 `FloatToNano(number=0.05) -> {"units": "0", "nano": 50000000}` 135 136 :param number: float number 137 :return: nano-type view of number: `{"units": "string", "nano": integer}` 138 """ 139 splitByPoint = str(number).split(".") 140 frac = 0 141 142 if len(splitByPoint) > 1: 143 if len(splitByPoint[1]) <= 9: 144 frac = int("{}{}".format( 145 int(splitByPoint[1]), 146 "0" * (9 - len(splitByPoint[1])), 147 )) 148 149 if (number < 0) and (frac > 0): 150 frac = -frac 151 152 return {"units": str(int(number)), "nano": frac}
39def GetDatesAsString(start: str = None, end: str = None, userFormat: str = "%Y-%m-%d", outputFormat: str = "%Y-%m-%dT%H:%M:%SZ") -> tuple[str, str]: 40 """ 41 Create tuple of date and time strings with timezone parsed from user-friendly date. 42 43 Warning! All dates must be in UTC time zone! 44 45 User dates format must be like: `"%Y-%m-%d"`, e.g. `"2020-02-03"` (3 Feb, 2020). 46 47 Output date is UTC ISO time format by default: `"%Y-%m-%dT%H:%M:%SZ"`. 48 49 Example input: `start="2022-06-01", end="2022-06-20"` -> output: `("2022-06-01T00:00:00Z", "2022-06-20T23:59:59Z")`. 50 An error exception will occur if input date has incorrect format. 51 52 If `start=None`, `end=None` then return dates from yesterday to the end of the day. 53 54 If `start=some_date_1`, `end=None` then return dates from `some_date_1` to the end of the day. 55 56 If `start=some_date_1`, `end=some_date_2` then return dates from start of `some_date_1` to end of `some_date_2`. 57 58 Start day may be negative integer numbers: `-1`, `-2`, `-3` — how many days ago. 59 60 Also, you can use keywords for start if `end=None`: 61 - `today` (from 00:00:00 to the end of current day), 62 - `yesterday` (-1 day from 00:00:00 to 23:59:59), 63 - `week` (-7 day from 00:00:00 to the end of current day), 64 - `month` (-30 day from 00:00:00 to the end of current day), 65 - `year` (-365 day from 00:00:00 to the end of current day), 66 67 :param start: start day in format defined by `userFormat` or keyword. 68 :param end: end day in format defined by `userFormat`. 69 :param userFormat: user-friendly date format, e.g. `"%Y-%m-%d"`. 70 :param outputFormat: output string date format. 71 :return: tuple with 2 strings `("start", "end")`. Example of return is `("2022-06-01T00:00:00Z", "2022-06-20T23:59:59Z")`. 72 Second string is the end of the last day. 73 """ 74 s = datetime.now(tzutc()).replace(hour=0, minute=0, second=0, microsecond=0) # start of the current day 75 e = s.replace(hour=23, minute=59, second=59, microsecond=0) # end of the current day 76 77 # time between start and the end of the current day: 78 if start is None or start.lower() == "today": 79 pass 80 81 # from start of the last day to the end of the last day: 82 elif start.lower() == "yesterday": 83 s -= timedelta(days=1) 84 e -= timedelta(days=1) 85 86 # week (-7 day from 00:00:00 to the end of the current day): 87 elif start.lower() == "week": 88 s -= timedelta(days=6) # +1 current day already taken into account 89 90 # month (-30 day from 00:00:00 to the end of current day): 91 elif start.lower() == "month": 92 s -= timedelta(days=29) # +1 current day already taken into account 93 94 # year (-365 day from 00:00:00 to the end of current day): 95 elif start.lower() == "year": 96 s -= timedelta(days=364) # +1 current day already taken into account 97 98 # -N days ago to the end of current day: 99 elif start.startswith('-') and start[1:].isdigit(): 100 s -= timedelta(days=abs(int(start)) - 1) # +1 current day already taken into account 101 102 # dates between start day at 00:00:00 and the end of the last day at 23:59:59: 103 else: 104 s = datetime.strptime(start, userFormat).replace(hour=0, minute=0, second=0, microsecond=0, tzinfo=tzutc()) 105 e = datetime.strptime(end, userFormat).replace(hour=23, minute=59, second=59, microsecond=0, tzinfo=tzutc()) if end is not None else e 106 107 # converting to UTC ISO time formatted with Z suffix for Tinkoff Open API: 108 s = s.strftime(outputFormat) 109 e = e.strftime(outputFormat) 110 111 return s, e
Create tuple of date and time strings with timezone parsed from user-friendly date.
Warning! All dates must be in UTC time zone!
User dates format must be like: "%Y-%m-%d"
, e.g. "2020-02-03"
(3 Feb, 2020).
Output date is UTC ISO time format by default: "%Y-%m-%dT%H:%M:%SZ"
.
Example input: start="2022-06-01", end="2022-06-20"
-> output: ("2022-06-01T00:00:00Z", "2022-06-20T23:59:59Z")
.
An error exception will occur if input date has incorrect format.
If start=None
, end=None
then return dates from yesterday to the end of the day.
If start=some_date_1
, end=None
then return dates from some_date_1
to the end of the day.
If start=some_date_1
, end=some_date_2
then return dates from start of some_date_1
to end of some_date_2
.
Start day may be negative integer numbers: -1
, -2
, -3
— how many days ago.
Also, you can use keywords for start if end=None
:
today
(from 00:00:00 to the end of current day),yesterday
(-1 day from 00:00:00 to 23:59:59),week
(-7 day from 00:00:00 to the end of current day),month
(-30 day from 00:00:00 to the end of current day),year
(-365 day from 00:00:00 to the end of current day),
Parameters
- start: start day in format defined by
userFormat
or keyword. - end: end day in format defined by
userFormat
. - userFormat: user-friendly date format, e.g.
"%Y-%m-%d"
. - outputFormat: output string date format.
Returns
tuple with 2 strings
("start", "end")
. Example of return is("2022-06-01T00:00:00Z", "2022-06-20T23:59:59Z")
. Second string is the end of the last day.
114def NanoToFloat(units: str, nano: int) -> float: 115 """ 116 Convert number in nano-view mode with string parameter `units` and integer parameter `nano` to float view. Examples: 117 118 `NanoToFloat(units="2", nano=500000000) -> 2.5` 119 120 `NanoToFloat(units="0", nano=50000000) -> 0.05` 121 122 :param units: integer string or integer parameter that represents the integer part of number 123 :param nano: integer string or integer parameter that represents the fractional part of number 124 :return: float view of number 125 """ 126 return int(units) + int(nano) * NANO
Convert number in nano-view mode with string parameter units
and integer parameter nano
to float view. Examples:
NanoToFloat(units="2", nano=500000000) -> 2.5
NanoToFloat(units="0", nano=50000000) -> 0.05
Parameters
- units: integer string or integer parameter that represents the integer part of number
- nano: integer string or integer parameter that represents the fractional part of number
Returns
float view of number
129def FloatToNano(number: float) -> dict: 130 """ 131 Convert float number to nano-type view: dictionary with string `units` and integer `nano` parameters `{"units": "string", "nano": integer}`. Examples: 132 133 `FloatToNano(number=2.5) -> {"units": "2", "nano": 500000000}` 134 135 `FloatToNano(number=0.05) -> {"units": "0", "nano": 50000000}` 136 137 :param number: float number 138 :return: nano-type view of number: `{"units": "string", "nano": integer}` 139 """ 140 splitByPoint = str(number).split(".") 141 frac = 0 142 143 if len(splitByPoint) > 1: 144 if len(splitByPoint[1]) <= 9: 145 frac = int("{}{}".format( 146 int(splitByPoint[1]), 147 "0" * (9 - len(splitByPoint[1])), 148 )) 149 150 if (number < 0) and (frac > 0): 151 frac = -frac 152 153 return {"units": str(int(number)), "nano": frac}
Convert float number to nano-type view: dictionary with string units
and integer nano
parameters {"units": "string", "nano": integer}
. Examples:
FloatToNano(number=2.5) -> {"units": "2", "nano": 500000000}
FloatToNano(number=0.05) -> {"units": "0", "nano": 50000000}
Parameters
- number: float number
Returns
nano-type view of number:
{"units": "string", "nano": integer}