(20241223) Trading Symbols Listing Started (Zerodha Kite).
This commit is contained in:
@@ -36,6 +36,7 @@ sys.path.append(".")
|
||||
sys.path.append("..")
|
||||
|
||||
# My async utils:
|
||||
from utils_v2.database.async_mysql_v2 import AsyncMySQL
|
||||
from utils_v2.database.async_mongo_v2 import AsyncMongo
|
||||
from utils_v2.cache.async_redis_cache_v2 import AsyncRedisCache
|
||||
|
||||
@@ -44,6 +45,7 @@ from controllers_v2.finstitutions.trading.base import TradingController
|
||||
|
||||
# Models:
|
||||
from models.core.auth_token import CoreAuthTokenModel
|
||||
from models.api.finstitutions.trading.symbols.list import TradingSymbolListRequestData, TradingSymbolListBrokerResponse
|
||||
|
||||
# To work with datatypes:
|
||||
from typing import List, Any
|
||||
@@ -131,7 +133,58 @@ class AllTradingController(TradingController):
|
||||
# ┣┫┓┏╋┣┓
|
||||
# ┛┗┗┻┗┛┗
|
||||
|
||||
pass
|
||||
@staticmethod
|
||||
async def get_authorization_url(
|
||||
**kwargs
|
||||
) -> str:
|
||||
|
||||
"""
|
||||
To generate an authorization URL for this broker.
|
||||
:param kwargs: Any no. of things needed by your broker to generate the URL.
|
||||
:return: The authorization URL.
|
||||
"""
|
||||
|
||||
raise NotImplementedError
|
||||
|
||||
async def handle_authorization_callback(
|
||||
self,
|
||||
sql_conn: AsyncMySQL,
|
||||
mongo_data_conn: AsyncMongo,
|
||||
inbound_data: dict
|
||||
) -> bool:
|
||||
"""
|
||||
When the end user interacts with their broker's APIs, the broker's servers would usually issue a callback.
|
||||
We've seen this in the case of Zerodha Kite and ICICI Breeze. Use this method to handle the callback loop to
|
||||
complete the authorization.
|
||||
:param sql_conn: The database connection to use to perform this activity.
|
||||
:param mongo_data_conn: The database connection to use to perform this activity.
|
||||
:param inbound_data: The data that came in from the broker. This could be in the JSON body, query params, etc.
|
||||
:return: True if the callback loop was completed successfully, else False.
|
||||
"""
|
||||
|
||||
raise NotImplementedError
|
||||
|
||||
# ┏┳┓ ┓• ┏┓ ┓ ┓
|
||||
# ┃ ┏┓┏┓┏┫┓┏┓┏┓ ┗┓┓┏┏┳┓┣┓┏┓┃┏
|
||||
# ┻ ┛ ┗┻┗┻┗┛┗┗┫ ┗┛┗┫┛┗┗┗┛┗┛┗┛
|
||||
# ┛ ┛
|
||||
|
||||
async def list_symbols(
|
||||
self,
|
||||
mongo_data_conn: AsyncMongo,
|
||||
auth_token: CoreAuthTokenModel,
|
||||
inbound_data: TradingSymbolListRequestData
|
||||
) -> TradingSymbolListBrokerResponse:
|
||||
|
||||
"""
|
||||
To get the list of tradeable symbols offered by a broker.
|
||||
:param mongo_data_conn: The database connection to use to perform this activity.
|
||||
:param auth_token: The token that has to be used to fetch the data.
|
||||
:param inbound_data: The data that came in with the APi call.
|
||||
:return: The structured response form the broker.
|
||||
"""
|
||||
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
|
||||
@@ -36,6 +36,7 @@ sys.path.append(".")
|
||||
sys.path.append("..")
|
||||
|
||||
# My async utils:
|
||||
from utils_v2.database.async_mysql_v2 import AsyncMySQL
|
||||
from utils_v2.database.async_mongo_v2 import AsyncMongo
|
||||
from utils_v2.cache.async_redis_cache_v2 import AsyncRedisCache
|
||||
|
||||
@@ -44,6 +45,7 @@ from controllers_v2.core.auth_token import CoreAuthTokenController
|
||||
|
||||
# Models:
|
||||
from models.core.auth_token import CoreAuthTokenModel
|
||||
from models.api.finstitutions.trading.symbols.list import TradingSymbolListRequestData, TradingSymbolListBrokerResponse
|
||||
|
||||
# To work with datatypes:
|
||||
from typing import List, Any
|
||||
@@ -149,7 +151,62 @@ class TradingController(CoreAuthTokenController, ABC):
|
||||
# ┣┫┓┏╋┣┓
|
||||
# ┛┗┗┻┗┛┗
|
||||
|
||||
pass
|
||||
@staticmethod
|
||||
@abstractmethod
|
||||
async def get_authorization_url(
|
||||
**kwargs
|
||||
) -> str:
|
||||
|
||||
"""
|
||||
To generate an authorization URL for this broker.
|
||||
:param kwargs: Any no. of things needed by your broker to generate the URL.
|
||||
:return: The authorization URL.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def handle_authorization_callback(
|
||||
self,
|
||||
sql_conn: AsyncMySQL,
|
||||
mongo_data_conn: AsyncMongo,
|
||||
inbound_data: dict
|
||||
) -> bool:
|
||||
|
||||
"""
|
||||
When the end user interacts with their broker's APIs, the broker's servers would usually issue a callback.
|
||||
We've seen this in the case of Zerodha Kite and ICICI Breeze. Use this method to handle the callback loop to
|
||||
complete the authorization.
|
||||
:param sql_conn: The database connection to use to perform this activity.
|
||||
:param mongo_data_conn: The database connection to use to perform this activity.
|
||||
:param inbound_data: The data that came in from the broker. This could be in the JSON body, query params, etc.
|
||||
:return: True if the callback loop was completed successfully, else False.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
# ┏┳┓ ┓• ┏┓ ┓ ┓
|
||||
# ┃ ┏┓┏┓┏┫┓┏┓┏┓ ┗┓┓┏┏┳┓┣┓┏┓┃┏
|
||||
# ┻ ┛ ┗┻┗┻┗┛┗┗┫ ┗┛┗┫┛┗┗┗┛┗┛┗┛
|
||||
# ┛ ┛
|
||||
|
||||
@abstractmethod
|
||||
async def list_symbols(
|
||||
self,
|
||||
mongo_data_conn: AsyncMongo,
|
||||
auth_token: CoreAuthTokenModel,
|
||||
inbound_data: TradingSymbolListRequestData
|
||||
) -> TradingSymbolListBrokerResponse:
|
||||
|
||||
"""
|
||||
To get the list of tradeable symbols offered by a broker.
|
||||
:param mongo_data_conn: The database connection to use to perform this activity.
|
||||
:param auth_token: The token that has to be used to fetch the data.
|
||||
:param inbound_data: The data that came in with the APi call.
|
||||
:return: The structured response form the broker.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
|
||||
@@ -47,6 +47,11 @@ from controllers_v2.finstitutions.trading.base import TradingController
|
||||
# Models:
|
||||
from models.core.auth_token import CoreAuthTokenModel
|
||||
from utils_v2.trading.zerodha_kite.models.auth_tokens import ZerodhaKiteAuthTokens
|
||||
from models.api.finstitutions.trading.symbols.list import (
|
||||
TradingSymbolListRequestData,
|
||||
TradingSymbolListBrokerResponse,
|
||||
TradingSymbol
|
||||
)
|
||||
|
||||
# To work with MongoDB:
|
||||
from bson.objectid import ObjectId
|
||||
@@ -100,6 +105,12 @@ from kiteconnect import KiteConnect
|
||||
|
||||
class ZerodhaKiteTradingController(TradingController):
|
||||
|
||||
# ┏┓┓ ┓┏
|
||||
# ┃ ┃┏┓┏┏ ┃┃┏┓┏┓┏
|
||||
# ┗┛┗┗┻┛┛ ┗┛┗┻┛ ┛
|
||||
|
||||
CLIENT_NAME = "zerodhaKite"
|
||||
|
||||
# ┏┓
|
||||
# ┃ ┏┓┏┓┏╋┏┓┓┏┏╋┏┓┏┓
|
||||
# ┗┛┗┛┛┗┛┗┛ ┗┻┗┗┗┛┛
|
||||
@@ -125,7 +136,7 @@ class ZerodhaKiteTradingController(TradingController):
|
||||
"""
|
||||
|
||||
# Declare the client:
|
||||
this_client = "zerodhaKite"
|
||||
this_client = self.CLIENT_NAME
|
||||
|
||||
# Prepare base filter:
|
||||
this_filter = {"client": this_client}
|
||||
@@ -179,7 +190,7 @@ class ZerodhaKiteTradingController(TradingController):
|
||||
:param sql_conn: The database connection to use to perform this activity.
|
||||
:param mongo_data_conn: The database connection to use to perform this activity.
|
||||
:param inbound_data: The data that came in from the broker. This could be in the JSON body, query params, etc.
|
||||
:return: The model that hold the access tokens, or None if something failed.
|
||||
:return: True if the callback loop was completed successfully, else False..
|
||||
"""
|
||||
|
||||
# Start by assuming failure:
|
||||
@@ -229,6 +240,55 @@ class ZerodhaKiteTradingController(TradingController):
|
||||
# Done here:
|
||||
return success
|
||||
|
||||
# ┏┳┓ ┓• ┏┓ ┓ ┓
|
||||
# ┃ ┏┓┏┓┏┫┓┏┓┏┓ ┗┓┓┏┏┳┓┣┓┏┓┃┏
|
||||
# ┻ ┛ ┗┻┗┻┗┛┗┗┫ ┗┛┗┫┛┗┗┗┛┗┛┗┛
|
||||
# ┛ ┛
|
||||
|
||||
async def list_symbols(
|
||||
self,
|
||||
mongo_data_conn: AsyncMongo,
|
||||
auth_token: CoreAuthTokenModel,
|
||||
inbound_data: TradingSymbolListRequestData
|
||||
) -> TradingSymbolListBrokerResponse:
|
||||
|
||||
"""
|
||||
To get the list of tradeable symbols offered by Zerodha.
|
||||
:param mongo_data_conn: The database connection to use to perform this activity.
|
||||
:param auth_token: The token that has to be used to fetch the data.
|
||||
:param inbound_data: The data that came in with the APi call.
|
||||
:return: The structured response form the broker.
|
||||
"""
|
||||
|
||||
# Start by assuming failure:
|
||||
symbol_list = TradingSymbolListBrokerResponse()
|
||||
|
||||
try:
|
||||
|
||||
# Fit the token into the model:
|
||||
zerodha_token = ZerodhaKiteAuthTokens(**auth_token.token)
|
||||
|
||||
# Now create an instance of the Kite:
|
||||
kite = KiteConnect(api_key = auth_token.auth["apiKey"])
|
||||
kite.set_access_token(zerodha_token.accessToken)
|
||||
|
||||
# Now we retrieve the list of symbols for every kind of exchange:
|
||||
symbol_list.data = []
|
||||
for exchange in inbound_data.exchanges:
|
||||
symbols_subset = kite.instruments(exchange = exchange)
|
||||
symbols_subset = [TradingSymbol.from_zerodha_kite(s) for s in symbols_subset[:10]]
|
||||
symbol_list.data += symbols_subset
|
||||
symbol_list.success = True
|
||||
symbol_list.message = "Symbol list retrieved successfully."
|
||||
|
||||
# In case something goes wrong:
|
||||
except Exception as exception:
|
||||
symbol_list.exception = exception
|
||||
symbol_list.message = str(exception)
|
||||
|
||||
# Done here:
|
||||
return symbol_list
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
|
||||
Reference in New Issue
Block a user