3a64ea7efe
git-subtree-dir: utils_v2 git-subtree-split: 8bb584e4734606740c0b42d51bc7fd458c39031a
223 lines
7.4 KiB
Python
223 lines
7.4 KiB
Python
"""
|
|
|
|
AUTHOR:
|
|
|
|
Khushal P Soonderji
|
|
|
|
DATE:
|
|
|
|
Monday, 6th Jan., 2024.
|
|
|
|
OBJECTIVE:
|
|
|
|
To provide a data model for describing the instruments supported by Zerodha Kite.
|
|
|
|
REFERENCES:
|
|
|
|
N/A
|
|
|
|
DOWNLOADS:
|
|
|
|
N/A
|
|
|
|
"""
|
|
|
|
|
|
# *****************************************************************************************************************
|
|
# ***** ****
|
|
# *** IMPORT ***
|
|
# ***** ****
|
|
# *****************************************************************************************************************
|
|
|
|
|
|
# To make sibling directories accessible for imports:
|
|
import sys
|
|
sys.path.append(".")
|
|
sys.path.append("..")
|
|
|
|
# For system-level activities:
|
|
import io
|
|
|
|
# For making data behaviour_models:
|
|
from pydantic import BaseModel, Field, field_validator, model_validator, AwareDatetime
|
|
from typing import Optional, Literal, Union, Dict, List, Any
|
|
|
|
# Related to Google:
|
|
from google.auth.transport.requests import Request
|
|
from google.oauth2.credentials import Credentials
|
|
|
|
# My utils:
|
|
from utils_v2.string import json
|
|
from utils_v2.string import regex
|
|
from utils_v2.date_time import date_time
|
|
|
|
# To work with date and time:
|
|
import datetime
|
|
import dateparser
|
|
|
|
# For working with tabulated data:
|
|
import pandas as pd
|
|
|
|
# To make API calls:
|
|
import httpx
|
|
|
|
|
|
# *****************************************************************************************************************
|
|
# ***** ****
|
|
# *** MACROS / ONE-TIME INIT ***
|
|
# ***** ****
|
|
# *****************************************************************************************************************
|
|
|
|
|
|
# --- Nothing Yet
|
|
|
|
|
|
# *****************************************************************************************************************
|
|
# ***** ****
|
|
# *** VARIABLES ***
|
|
# ***** ****
|
|
# *****************************************************************************************************************
|
|
|
|
|
|
# --- Nothing Yet
|
|
|
|
|
|
# *****************************************************************************************************************
|
|
# ***** ****
|
|
# *** FUNCTIONS ***
|
|
# ***** ****
|
|
# *****************************************************************************************************************
|
|
|
|
|
|
class ZerodhaKiteInstrument(BaseModel):
|
|
|
|
instrumentToken: int = Field(
|
|
description = "The token by which Zerodha recognizes this instrument.",
|
|
frozen = True,
|
|
alias = "instrument_token"
|
|
)
|
|
|
|
exchangeToken: int | str = Field(
|
|
description = "The way the exchange recognizes this instrument.",
|
|
frozen = True,
|
|
alias = "exchange_token"
|
|
)
|
|
|
|
symbol: str | None = Field(
|
|
description = "The trading symbol pf this instrument.",
|
|
frozen = True,
|
|
alias = "tradingsymbol"
|
|
)
|
|
|
|
name: str | None = Field(
|
|
description = "The name of the company (for stocks), or the trading symbol (for derivatives).",
|
|
frozen = True,
|
|
alias = "name"
|
|
)
|
|
|
|
ltp: float | int = Field(
|
|
description = "The last price at which this instrument was traded.",
|
|
frozen = True,
|
|
alias = "last_price"
|
|
)
|
|
|
|
expiry: str | None = Field(
|
|
description = "The expiry date (if derivative).",
|
|
frozen = True,
|
|
alias = "expiry"
|
|
)
|
|
|
|
strike: float | int | None = Field(
|
|
description = "The strike price (if option).",
|
|
frozen = True,
|
|
alias = "strike"
|
|
)
|
|
|
|
tickSize: float | int = Field(
|
|
description = "The minimum value by which the price must move to change.",
|
|
frozen = True,
|
|
alias = "tick_size"
|
|
)
|
|
|
|
lotSize: float | int = Field(
|
|
description = "The minimum trading qty. (if derivative).",
|
|
frozen = True,
|
|
alias = "lot_size"
|
|
)
|
|
|
|
segment: str = Field(
|
|
description = "The segment that the instrument belongs to.",
|
|
frozen = True,
|
|
alias = "segment"
|
|
)
|
|
|
|
instrumentType: str = Field(
|
|
description = "the subtype of the 'segment'.",
|
|
frozen = True,
|
|
alias = "instrument_type"
|
|
)
|
|
|
|
exchange: str = Field(
|
|
description = "The exchange on which this instrument is traded.",
|
|
alias = "exchange"
|
|
)
|
|
|
|
# ┏┓ ┏•
|
|
# ┃ ┏┓┏┓╋┓┏┓
|
|
# ┗┛┗┛┛┗┛┗┗┫
|
|
# ┛
|
|
|
|
class Config:
|
|
extra = "ignore"
|
|
populate_by_name = True
|
|
|
|
# ┓┏ ┓• ┓ •
|
|
# ┃┃┏┓┃┓┏┫┏┓╋┓┏┓┏┓
|
|
# ┗┛┗┻┗┗┗┻┗┻┗┗┗┛┛┗
|
|
|
|
pass
|
|
|
|
# ┏┓ •
|
|
# ┃┃┏┓┏┓┏┓┏┓┏┓╋┓┏┓┏
|
|
# ┣┛┛ ┗┛┣┛┗ ┛ ┗┗┗ ┛
|
|
# ┛
|
|
|
|
pass
|
|
|
|
# ┏┓ ┏┓
|
|
# ┃ ┓┏┏╋┏┓┏┳┓ ┣ ┓┏┏┓┏┏
|
|
# ┗┛┗┻┛┗┗┛┛┗┗ ┻ ┗┻┛┗┗┛
|
|
|
|
def __str__(self):
|
|
return f"{self.exchange}:{self.symbol}"
|
|
|
|
def __repr__(self):
|
|
return str(self)
|
|
|
|
@staticmethod
|
|
def from_api_data(api_data: bytes | io.BytesIO | pd.DataFrame | List[dict] | dict) -> "ZerodhaKiteInstrument":
|
|
|
|
# Convert the input to a list of dicts:
|
|
if isinstance(api_data, bytes): api_data = io.BytesIO(api_data)
|
|
if isinstance(api_data, io.BytesIO): api_data = pd.read_csv(api_data)
|
|
if isinstance(api_data, pd.DataFrame):
|
|
api_data = api_data.map(lambda x: None if pd.isna(x) else x)
|
|
api_data = api_data.to_dict(orient = "records")
|
|
if isinstance(api_data, dict): api_data = [api_data]
|
|
|
|
# Model the records and return the values:
|
|
modelled_instruments = [ZerodhaKiteInstrument(**instrument) for instrument in api_data]
|
|
return modelled_instruments
|
|
|
|
|
|
# *****************************************************************************************************************
|
|
# ***** ****
|
|
# *** MAIN PROGRAM ***
|
|
# ***** ****
|
|
# *****************************************************************************************************************
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
pass
|