From 5778a14fe867cf8b59f1d032a234b315f198126a Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Tue, 27 Oct 2020 12:39:52 +0530 Subject: [PATCH 01/49] file added --- SmartApi/__init__.py | 0 SmartApi/smartConnect.py | 353 ++++++++++++++++++++++++++++++++++++ SmartApi/smartExceptions.py | 62 +++++++ SmartApi/test.py | 46 +++++ SmartApi/version.py | 8 + test/__init__.py | Bin 0 -> 24 bytes test/test.py | 54 ++++++ 7 files changed, 523 insertions(+) create mode 100644 SmartApi/__init__.py create mode 100644 SmartApi/smartConnect.py create mode 100644 SmartApi/smartExceptions.py create mode 100644 SmartApi/test.py create mode 100644 SmartApi/version.py create mode 100644 test/__init__.py create mode 100644 test/test.py diff --git a/SmartApi/__init__.py b/SmartApi/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/SmartApi/smartConnect.py b/SmartApi/smartConnect.py new file mode 100644 index 0000000..85602a9 --- /dev/null +++ b/SmartApi/smartConnect.py @@ -0,0 +1,353 @@ +from six.moves.urllib.parse import urljoin +import sys +sys.path.append('c:\AngelSmartApi\SmartApi') +print (sys.path) +import csv +import json +import dateutil.parser +import hashlib +import logging +import datetime +import smartExceptions +import requests +from requests import get +import re, uuid +import socket + +from version import __version__, __title__ + +log = logging.getLogger(__name__) + + +class SmartConnect(object): + _rootUrl = "https://openapisuat.angelbroking.com" + _loginUrl = "https://openapisuat.angelbroking.com/login-service/rest/auth/angelbroking/user/v1/loginByPassword" + _default_timeout = 7 # In seconds + # Products + PRODUCT_MIS = "MIS" + PRODUCT_CNC = "CNC" + PRODUCT_NRML = "NRML" + PRODUCT_CO = "CO" + PRODUCT_BO = "BO" + + # Order types + ORDER_TYPE_MARKET = "MARKET" + ORDER_TYPE_LIMIT = "LIMIT" + ORDER_TYPE_SLM = "SL-M" + ORDER_TYPE_SL = "SL" + + # Varities + VARIETY_REGULAR = "regular" + VARIETY_BO = "bo" + VARIETY_CO = "co" + VARIETY_AMO = "amo" + + # Transaction type + TRANSACTION_TYPE_BUY = "BUY" + TRANSACTION_TYPE_SELL = "SELL" + + # Validity + VALIDITY_DAY = "DAY" + VALIDITY_IOC = "IOC" + + # Exchanges + EXCHANGE_NSE = "NSE" + EXCHANGE_BSE = "BSE" + EXCHANGE_NFO = "NFO" + EXCHANGE_CDS = "CDS" + EXCHANGE_BFO = "BFO" + EXCHANGE_MCX = "MCX" + + # Status constants + STATUS_COMPLETE = "COMPLETE" + STATUS_REJECTED = "REJECTED" + STATUS_CANCELLED = "CANCELLED" + + _routes = { + "api.login":"/login-service/rest/auth/angelbroking/user/v1/loginByPassword", + "api.logout":"/login-service/rest/secure/angelbroking/user/v1/logout", + "api.token": "/login-service/rest/auth/angelbroking/jwt/v1/generateTokens", + "api.refresh": "/login-service/rest/auth/angelbroking/jwt/v1/generateTokens", + "api.user.profile": "/login-service/rest/secure/angelbroking/user/v1/getProfile", + + "api.order.place": "/order-service/rest/secure/angelbroking/order/v1/placeOrder", + "api.order.modify": "/order-service/rest/secure/angelbroking/order/v1/modifyOrder", + "api.order.cancel": "/order-service/rest/secure/angelbroking/order/v1/cancelOrder", + "api.order.book":"/order-service/rest/secure/angelbroking/order/v1/getOrderBook", + + "api.ltp.data": "/order-service/rest/secure/angelbroking/order/v1/getLtpData", + "api.trade.book": "/order-service/rest/secure/angelbroking/order/v1/getTradeBook", + "api.rms.limit": "/order-service/rest/secure/angelbroking/rms/v1/getRMS", + "api.holding": "/order-service/rest/secure/angelbroking/rms/v1/getHolding", + "api.position": "/order-service/rest/secure/angelbroking/rms/v1/getPosition", + "api.convert.position": "/order-service/rest/secure/angelbroking/rms/v1/convertPosition" + } + + def __init__(self, api_key=None, access_token=None, refresh_token=None, userId=None, root=None, debug=False, timeout=None, proxies=None, pool=None, disable_ssl=False): + self.debug = debug + self.api_key = api_key + self.session_expiry_hook = None + self.disable_ssl = disable_ssl + self.access_token = access_token + self.refresh_token = refresh_token + self.userId = userId + self.proxies = proxies if proxies else {} + self.root = root or self._loginUrl + self.timeout = timeout or self._default_timeout + + if pool: + self.reqsession = requests.Session() + reqadapter = requests.adapters.HTTPAdapter(**pool) + self.reqsession.mount("https://", reqadapter) + print("in pool") + else: + self.reqsession = requests + + # disable requests SSL warning + requests.packages.urllib3.disable_warnings() + + def setSessionExpiryHook(self, method): + if not callable(method): + raise TypeError("Invalid input type. Only functions are accepted.") + self.session_expiry_hook = method + + def getUserId(): + return userId; + + def setUserId(self,id): + self.userId=id + + def setAccessToken(self, access_token): + + self.access_token = access_token + + def setRefreshToken(self, refresh_token): + + self.refresh_token = refresh_token + + + def _request(self, route, method, parameters=None): + """Make an HTTP request.""" + params = parameters.copy() if parameters else {} + print(params) + uri =self._routes[route].format(**params) + #print(uri) + url = urljoin(self.root, uri) + print(url) + hostname = socket.gethostname() + clientLocalIP=socket.gethostbyname(hostname) + clientPublicIP=get('https://api.ipify.org').text + macAddress = ':'.join(re.findall('..', '%012x' % uuid.getnode())) + privateKey = "test" + accept = "application/json" + userType = "USER" + sourceID = "WEB" + + # Custom headers + headers = { + #"X-Kite-Version": "3", + #"User-Agent": self._user_agent(), + "Content-type":accept, + "X-ClientLocalIP": clientLocalIP, + "X-ClientPublicIP": clientPublicIP, + "X-MACAddress": macAddress, + "Accept": accept, + "X-PrivateKey": privateKey, + "X-UserType": userType, + "X-SourceID": sourceID + } + + #if self.api_key and self.access_token: + if self.access_token: + # set authorization header + print("11111111111111111",self.access_token) + auth_header = self.access_token + headers["Authorization"] = "Bearer {}".format(auth_header) + print(auth_header) + if self.debug: + log.debug("Request: {method} {url} {params} {headers}".format(method=method, url=url, params=params, headers=headers)) + print(headers) + try: + r = requests.request(method, + url, + data=json.dumps(params) if method in ["POST", "PUT"] else None, + params=json.dumps(params) if method in ["GET", "DELETE"] else None, + headers=headers, + verify=not self.disable_ssl, + allow_redirects=True, + timeout=self.timeout, + proxies=self.proxies) + print(r) + except Exception as e: + raise e + + if self.debug: + log.debug("Response: {code} {content}".format(code=r.status_code, content=r.content)) + + # Validate the content type. + if "json" in headers["Content-type"]: + try: + data = json.loads(r.content.decode("utf8")) + print("cgqkqwhxbqwxwuv",data) + except ValueError: + raise DataException("Couldn't parse the JSON response received from the server: {content}".format( + content=r.content)) + + # api error + if data.get("error_type"): + # Call session hook if its registered and TokenException is raised + if self.session_expiry_hook and r.status_code == 403 and data["error_type"] == "TokenException": + self.session_expiry_hook() + + # native Kite errors + exp = getattr(ex, data["error_type"], GeneralException) + raise exp(data["message"], code=r.status_code) + + return data + elif "csv" in headers["Content-type"]: + return r.content + else: + raise DataException("Unknown Content-type ({content_type}) with response: ({content})".format( + content_type=headers["Content-type"], + content=r.content)) + + def _deleteRequest(self, route, params=None): + """Alias for sending a DELETE request.""" + return self._request(route, "DELETE", params) + def _putRequest(self, route, params=None): + """Alias for sending a PUT request.""" + return self._request(route, "PUT", params) + def _postRequest(self, route, params=None): + """Alias for sending a POST request.""" + print("here",route,params) + return self._request(route, "POST", params) + def _getRequest(self, route, params=None): + """Alias for sending a GET request.""" + return self._request(route, "GET", params) + + def generateSession(self,clientCode,password): + print("Client Code:",clientCode,"Password:",password) + params={"clientcode":clientCode,"password":password} + loginResultObject=self._postRequest("api.login",params) + jwtToken=loginResultObject['data']['jwtToken'] + self.setAccessToken(jwtToken) + refreshToken=loginResultObject['data']['refreshToken'] + self.setRefreshToken(refreshToken) + user=self.getProfile(refreshToken) + print("User",user) + id=user['data']['clientcode'] + print(id) + self.setUserId(id) + user['data']['jwtToken']="Bearer "+jwtToken + user['data']['refreshToken']=refreshToken + return user + + def terminateSession(self,clientCode): + logoutResponseObject=self._postRequest("api.logout",{"clientcode":clientCode}) + return logoutResponseObject + + def generateToken(self,refresh_token): + response=self._postRequest('api.token',{"refreshToken":refresh_token}) + jwtToken=response['data']['jwtToken'] + self.setAccessToken(jwtToken) + return response + + def renewAccessToken(self): + + # h = hashlib.sha256(self.api_key.encode("utf-8") + refresh_token.encode("utf-8") + access_token.encode("utf-8")) + # checksum = h.hexdigest() + + response =self._postRequest('api.refresh', { + "jwtToken": self.access_token, + "refreshToken": self.refresh_token, + #"checksum": checksum + }) + print(response) + tokenSet={} + + if "jwtToken" in response: + tokenSet['jwtToken']=response['data']['jwtToken'] + tokenSet['clientcode']=self.userId + tokenSet['refreshToken']=response['data']["refreshToken"] + print(tokenSet) + return tokenSet + + def getProfile(self,refreshToken): + user=self._getRequest("api.user.profile",{"refreshToken":refreshToken}) + return user + + def placeOrder(self,orderparams): + #params = {"exchange":orderparams.exchange,"symbolToken":orderparams.symboltoken,"transactionType":orderparams.transactionType,"quantity":orderparams.quantity,"price":orderparams.price,"productType":orderparams.producttype,"orderType":orderparams.ordertype,"duration":orderparams.duration,"variety":orderparams.variety,"tradingSymbol":orderparams.tradingsymbol,"triggerPrice":orderparams.trigger_price,"squareoff":orderparams.squareoff,"stoploss":orderparams.stoploss,"trailingStoploss":orderparams.trailing_stoploss,"tag":orderparams.tag} + params=orderparams + print(params) + for k in list(params.keys()): + if params[k] is None : + del(params[k]) + + orderResponse= self._postRequest("api.order.place", params)['data']['orderid'] + print(orderResponse) + return orderResponse + + def modifyOrder(self,orderparams): + params = orderparams + + for k in list(params.keys()): + if params[k] is None: + del(params[k]) + + orderResponse= self._postRequest("api.order.modify", params) + #order=Order(orderResponse) + #order['orderId']=orderResponse['data']['orderid'] + return orderResponse + + def cancelOrder(self, order_id,variety): + orderResponse= self._postRequest("api.order.cancel", {"variety": variety,"orderid": order_id}) + return orderResponse + + def ltpData(self,exchange,tradingsymbol,symboltoken): + params={ + "exchange":exchange, + "tradingsymbol":tradingsymbol, + "symboltoken":symboltoken + } + ltpDataResponse= self._postRequest("api.ltp.data",params) + return ltpDataResponse + + def orderBook(self): + orderBookResponse=self._getRequest("api.order.book") + return orderBookResponse + + + def tradeBook(self): + tradeBookResponse=self._getRequest("api.trade.book") + return tradeBookResponse + + def rmsLimit(self): + rmsLimitResponse= self._getRequest("api.rms.limit") + return rmsLimitResponse + + def position(self): + positionResponse= self._getRequest("api.position") + return positionResponse + + def holding(self): + holdingResponse= self._getRequest("api.holding") + return holdingResponse + + def convertPosition(self,positionParams): + params=positionParams + for k in list(params.keys()): + if params[k] is None: + del(params[k]) + convertPositionResponse= self._postRequest("api.position.convert",params) + + return convertPositionResponse + + def _user_agent(self): + return (__title__ + "-python/").capitalize() + __version__ + + + + + + \ No newline at end of file diff --git a/SmartApi/smartExceptions.py b/SmartApi/smartExceptions.py new file mode 100644 index 0000000..6bf1984 --- /dev/null +++ b/SmartApi/smartExceptions.py @@ -0,0 +1,62 @@ +class SmartAPIException(Exception): + + def __init__(self, message, code=500): + """Initialize the exception.""" + super(SmartAPIException, self).__init__(message) + self.code = code + + +class GeneralException(SmartAPIException): + """An unclassified, general error. Default code is 500.""" + + def __init__(self, message, code=500): + """Initialize the exception.""" + super(GeneralException, self).__init__(message, code) + + +class TokenException(SmartAPIException): + """Represents all token and authentication related errors. Default code is 403.""" + + def __init__(self, message, code=403): + """Initialize the exception.""" + super(TokenException, self).__init__(message, code) + + +class PermissionException(SmartAPIException): + """Represents permission denied exceptions for certain calls. Default code is 403.""" + + def __init__(self, message, code=403): + """Initialize the exception.""" + super(PermissionException, self).__init__(message, code) + + +class OrderException(SmartAPIException): + """Represents all order placement and manipulation errors. Default code is 500.""" + + def __init__(self, message, code=500): + """Initialize the exception.""" + super(OrderException, self).__init__(message, code) + + +class InputException(SmartAPIException): + """Represents user input errors such as missing and invalid parameters. Default code is 400.""" + + def __init__(self, message, code=400): + """Initialize the exception.""" + super(InputException, self).__init__(message, code) + + +class DataException(SmartAPIException): + """Represents a bad response from the backend Order Management System (OMS). Default code is 502.""" + + def __init__(self, message, code=502): + """Initialize the exception.""" + super(DataException, self).__init__(message, code) + + +class NetworkException(SmartAPIException): + """Represents a network issue between Kite and the backend Order Management System (OMS). Default code is 503.""" + + def __init__(self, message, code=503): + """Initialize the exception.""" + super(NetworkException, self).__init__(message, code) diff --git a/SmartApi/test.py b/SmartApi/test.py new file mode 100644 index 0000000..d7cb08b --- /dev/null +++ b/SmartApi/test.py @@ -0,0 +1,46 @@ +from smartConnect import * +smartApi=SmartConnect() + +#login Api + +login=smartApi.generateSession('D88311','Angel@444') +refreshToken=login['data']['refreshToken'] +smartApi.generateToken(refreshToken) +orderparams={ + "variety": "NORMAL", + "tradingsymbol": "SBIN-EQ", + "symboltoken": "3045", + "transactiontype": "BUY", + "exchange": "NSE", + "ordertype": "LIMIT", + "producttype": "INTRADAY", + "duration": "DAY", + "price": "19500", + "squareoff": "0", + "stoploss": "0", + "quantity": "1" +} +orderid=smartApi.placeOrder(orderparams) + +modifyparams={ + "variety":"NORMAL", + "orderid":orderid, + "ordertype":"LIMIT", + "producttype":"INTRADAY", + "duration":"DAY", + "price":"19500", + "quantity":"1" +} +smartApi.modifyOrder(modifyparams) + +smartApi.cancelOrder(orderid,"NORMAL") + +smartApi.orderBook() +smartApi.tradeBook() +smartApi.rmsLimit() +smartApi.position() +smartApi.holding() +exchange="NSE" +tradingsymbol="SBIN-EQ" +symboltoken=3045 +smartApi.ltpData("NSE","SBIN-EQ","3045" ) \ No newline at end of file diff --git a/SmartApi/version.py b/SmartApi/version.py new file mode 100644 index 0000000..e68af5d --- /dev/null +++ b/SmartApi/version.py @@ -0,0 +1,8 @@ +__title__ = "smartconnect" +__description__ = "Angel openApi integration" +__url__ = "" +__download_url__ = "https://github.com/zerodhatech/pykiteconnect" +__version__ = "1.0.1" +__author__ = "Applied Cloud Computing Pvt ltd. (India)" +__author_email__ = "talk@zerodha.tech" +__license__ = "MIT" \ No newline at end of file diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..2193513aff00fe5030e585408735b6ffbabb6828 GIT binary patch literal 24 fcmWGaEK-zWXJj~dKR%3^k%d9FJS>ozm4yKSN{j^! literal 0 HcmV?d00001 diff --git a/test/test.py b/test/test.py new file mode 100644 index 0000000..da8e9f9 --- /dev/null +++ b/test/test.py @@ -0,0 +1,54 @@ +import sys +import os +dir=os.getcwd() +print(dir) +#path=dir.split("\") + +sys.path.append(dir+"\SmartApi") +print(sys.path) +import smartConnect +smartApi=smartConnect.SmartConnect() + +login=smartApi.generateSession('D88311','Angel@444') +refreshToken=login['data']['refreshToken'] +smartApi.getProfile(refreshToken) +smartApi.generateToken(refreshToken) +orderparams={ + "variety": "NORMAL", + "tradingsymbol": "SBIN-EQ", + "symboltoken": "3045", + "transactiontype": "BUY", + "exchange": "NSE", + "ordertype": "LIMIT", + "producttype": "INTRADAY", + "duration": "DAY", + "price": "19500", + "squareoff": "0", + "stoploss": "0", + "quantity": "1" +} +orderid=smartApi.placeOrder(orderparams) + +modifyparams={ + "variety":"NORMAL", + "orderid":orderid, + "ordertype":"LIMIT", + "producttype":"INTRADAY", + "duration":"DAY", + "price":"19500", + "quantity":"1" +} +smartApi.modifyOrder(modifyparams) + +smartApi.cancelOrder(orderid,"NORMAL") + +smartApi.orderBook() +smartApi.tradeBook() +smartApi.rmsLimit() +smartApi.position() +smartApi.holding() +exchange="NSE" +tradingsymbol="SBIN-EQ" +symboltoken=3045 +smartApi.ltpData("NSE","SBIN-EQ","3045" ) +smartApi.terminateSession(login['data']['clientcode']) \ No newline at end of file From 8149936fb4346b4c582947c24485dd11df8fdd21 Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Wed, 28 Oct 2020 12:37:47 +0530 Subject: [PATCH 02/49] Changes in code and addition of new files and folder in order to publish the package --- .pypirc | 10 + SmartApi/__pycache__/__init__.cpython-36.pyc | Bin 0 -> 122 bytes .../__pycache__/smartConnect.cpython-36.pyc | Bin 0 -> 10834 bytes .../smartExceptions.cpython-36.pyc | Bin 0 -> 3678 bytes SmartApi/__pycache__/version.cpython-36.pyc | Bin 0 -> 480 bytes SmartApi/smartConnect.py | 48 +-- SmartApi/test.py | 46 --- SmartApi/version.py | 19 +- build/lib/smartapi/__init__.py | 0 build/lib/smartapi/smartConnect.py | 353 ++++++++++++++++++ build/lib/smartapi/smartExceptions.py | 62 +++ build/lib/smartapi/version.py | 13 + dist/smartapi-python-1.0.1.tar.gz | Bin 0 -> 6141 bytes dist/smartapi_python-1.0.1-py3-none-any.whl | Bin 0 -> 6601 bytes example/sample.py | 17 + requirements_dev.txt | 2 + setup.py | 40 ++ smartapi_python.egg-info/PKG-INFO | 24 ++ smartapi_python.egg-info/SOURCES.txt | 12 + smartapi_python.egg-info/dependency_links.txt | 1 + smartapi_python.egg-info/requires.txt | 3 + smartapi_python.egg-info/top_level.txt | 1 + 22 files changed, 575 insertions(+), 76 deletions(-) create mode 100644 .pypirc create mode 100644 SmartApi/__pycache__/__init__.cpython-36.pyc create mode 100644 SmartApi/__pycache__/smartConnect.cpython-36.pyc create mode 100644 SmartApi/__pycache__/smartExceptions.cpython-36.pyc create mode 100644 SmartApi/__pycache__/version.cpython-36.pyc delete mode 100644 SmartApi/test.py create mode 100644 build/lib/smartapi/__init__.py create mode 100644 build/lib/smartapi/smartConnect.py create mode 100644 build/lib/smartapi/smartExceptions.py create mode 100644 build/lib/smartapi/version.py create mode 100644 dist/smartapi-python-1.0.1.tar.gz create mode 100644 dist/smartapi_python-1.0.1-py3-none-any.whl create mode 100644 example/sample.py create mode 100644 requirements_dev.txt create mode 100644 setup.py create mode 100644 smartapi_python.egg-info/PKG-INFO create mode 100644 smartapi_python.egg-info/SOURCES.txt create mode 100644 smartapi_python.egg-info/dependency_links.txt create mode 100644 smartapi_python.egg-info/requires.txt create mode 100644 smartapi_python.egg-info/top_level.txt diff --git a/.pypirc b/.pypirc new file mode 100644 index 0000000..13da8a9 --- /dev/null +++ b/.pypirc @@ -0,0 +1,10 @@ +[distutils] +index-servers = + pypi + +[pypi] +repository: https://upload.pypi.org/legacy/ +username: ab-smartapi +password: Smart#54321 + + diff --git a/SmartApi/__pycache__/__init__.cpython-36.pyc b/SmartApi/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d9cb64366e71c1538c60371f05df7862bf84ba8a GIT binary patch literal 122 zcmXr!<>lHSGcle42p)q77+?f49Dul(1xTbY1T$zd`mJOr0tq9CU+T_QF~zxwMJ0&^ qnYsm)B^mj7aDGgDd}dx|NqoFsLFFwDo80`A(wtN~kO9R&%m4sgEE~W8 literal 0 HcmV?d00001 diff --git a/SmartApi/__pycache__/smartConnect.cpython-36.pyc b/SmartApi/__pycache__/smartConnect.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..00ec287a665bf091d2fe9957b3f1c4835ce8c4ac GIT binary patch literal 10834 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 literal 0 HcmV?d00001 diff --git a/SmartApi/__pycache__/version.cpython-36.pyc b/SmartApi/__pycache__/version.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6aaf2ef211964cbff76088ad4f5a9f8196158c70 GIT binary patch literal 480 zcmZ8ey>7xV5Kj0B1cYGfR*5cE8AysMbwE`G?bM-N=wu;T23x_xi6h%-MBb#2&{xXZ zx9HR}Arh^vJDtA!?#G|+27{jGed2k;alW0i<3hXu(>LI#gBZ%v z8_c5~>d+4A((cNc_{C7iL>ZFuX?id_nG{#cBw}Lxq~x9_(O9M|S*Co<6T>1!3k+y=9vPd3v!Rb13jpy_@Q z#e@snuWY`)yuVHS(#P0vBN)cz5M#>pR`Jv>2|x$qObLw92r@EHge0^=%09*)OzDc( z!{vjcO7Ja9G>rRlln+WD-Ou&&d|fYk(s8}Ax`J}+)1V+d Ul--9|(oC>N`&)VhuI2u{zsTyDNB{r; literal 0 HcmV?d00001 diff --git a/SmartApi/smartConnect.py b/SmartApi/smartConnect.py index 85602a9..a753e0c 100644 --- a/SmartApi/smartConnect.py +++ b/SmartApi/smartConnect.py @@ -1,7 +1,6 @@ from six.moves.urllib.parse import urljoin import sys sys.path.append('c:\AngelSmartApi\SmartApi') -print (sys.path) import csv import json import dateutil.parser @@ -129,11 +128,9 @@ def setRefreshToken(self, refresh_token): def _request(self, route, method, parameters=None): """Make an HTTP request.""" params = parameters.copy() if parameters else {} - print(params) + print("Request params:",params) uri =self._routes[route].format(**params) - #print(uri) url = urljoin(self.root, uri) - print(url) hostname = socket.gethostname() clientLocalIP=socket.gethostbyname(hostname) clientPublicIP=get('https://api.ipify.org').text @@ -160,13 +157,12 @@ def _request(self, route, method, parameters=None): #if self.api_key and self.access_token: if self.access_token: # set authorization header - print("11111111111111111",self.access_token) + auth_header = self.access_token headers["Authorization"] = "Bearer {}".format(auth_header) - print(auth_header) if self.debug: log.debug("Request: {method} {url} {params} {headers}".format(method=method, url=url, params=params, headers=headers)) - print(headers) + try: r = requests.request(method, url, @@ -188,7 +184,7 @@ def _request(self, route, method, parameters=None): if "json" in headers["Content-type"]: try: data = json.loads(r.content.decode("utf8")) - print("cgqkqwhxbqwxwuv",data) + print("The Reponse Content",data) except ValueError: raise DataException("Couldn't parse the JSON response received from the server: {content}".format( content=r.content)) @@ -229,18 +225,24 @@ def generateSession(self,clientCode,password): print("Client Code:",clientCode,"Password:",password) params={"clientcode":clientCode,"password":password} loginResultObject=self._postRequest("api.login",params) - jwtToken=loginResultObject['data']['jwtToken'] - self.setAccessToken(jwtToken) - refreshToken=loginResultObject['data']['refreshToken'] - self.setRefreshToken(refreshToken) - user=self.getProfile(refreshToken) - print("User",user) - id=user['data']['clientcode'] - print(id) - self.setUserId(id) - user['data']['jwtToken']="Bearer "+jwtToken - user['data']['refreshToken']=refreshToken - return user + if "jwtToken" and "refreshToken" in loginResultObject: + jwtToken=loginResultObject['data']['jwtToken'] + refreshToken=loginResultObject['data']['refreshToken'] + self.setAccessToken(jwtToken) + self.setRefreshToken(refreshToken) + user=self.getProfile(refreshToken) + print("User",user) + id=user['data']['clientcode'] + print(id) + self.setUserId(id) + user['data']['jwtToken']="Bearer "+jwtToken + user['data']['refreshToken']=refreshToken + return user + + else: + print("Password or Userid is incorrect or expired") + + def terminateSession(self,clientCode): logoutResponseObject=self._postRequest("api.logout",{"clientcode":clientCode}) @@ -262,7 +264,7 @@ def renewAccessToken(self): "refreshToken": self.refresh_token, #"checksum": checksum }) - print(response) + tokenSet={} if "jwtToken" in response: @@ -279,13 +281,13 @@ def getProfile(self,refreshToken): def placeOrder(self,orderparams): #params = {"exchange":orderparams.exchange,"symbolToken":orderparams.symboltoken,"transactionType":orderparams.transactionType,"quantity":orderparams.quantity,"price":orderparams.price,"productType":orderparams.producttype,"orderType":orderparams.ordertype,"duration":orderparams.duration,"variety":orderparams.variety,"tradingSymbol":orderparams.tradingsymbol,"triggerPrice":orderparams.trigger_price,"squareoff":orderparams.squareoff,"stoploss":orderparams.stoploss,"trailingStoploss":orderparams.trailing_stoploss,"tag":orderparams.tag} params=orderparams - print(params) + print("placeOrder params",params) for k in list(params.keys()): if params[k] is None : del(params[k]) orderResponse= self._postRequest("api.order.place", params)['data']['orderid'] - print(orderResponse) + print("The placeOrder",orderResponse) return orderResponse def modifyOrder(self,orderparams): diff --git a/SmartApi/test.py b/SmartApi/test.py deleted file mode 100644 index d7cb08b..0000000 --- a/SmartApi/test.py +++ /dev/null @@ -1,46 +0,0 @@ -from smartConnect import * -smartApi=SmartConnect() - -#login Api - -login=smartApi.generateSession('D88311','Angel@444') -refreshToken=login['data']['refreshToken'] -smartApi.generateToken(refreshToken) -orderparams={ - "variety": "NORMAL", - "tradingsymbol": "SBIN-EQ", - "symboltoken": "3045", - "transactiontype": "BUY", - "exchange": "NSE", - "ordertype": "LIMIT", - "producttype": "INTRADAY", - "duration": "DAY", - "price": "19500", - "squareoff": "0", - "stoploss": "0", - "quantity": "1" -} -orderid=smartApi.placeOrder(orderparams) - -modifyparams={ - "variety":"NORMAL", - "orderid":orderid, - "ordertype":"LIMIT", - "producttype":"INTRADAY", - "duration":"DAY", - "price":"19500", - "quantity":"1" -} -smartApi.modifyOrder(modifyparams) - -smartApi.cancelOrder(orderid,"NORMAL") - -smartApi.orderBook() -smartApi.tradeBook() -smartApi.rmsLimit() -smartApi.position() -smartApi.holding() -exchange="NSE" -tradingsymbol="SBIN-EQ" -symboltoken=3045 -smartApi.ltpData("NSE","SBIN-EQ","3045" ) \ No newline at end of file diff --git a/SmartApi/version.py b/SmartApi/version.py index e68af5d..a7b5a3e 100644 --- a/SmartApi/version.py +++ b/SmartApi/version.py @@ -1,8 +1,13 @@ -__title__ = "smartconnect" -__description__ = "Angel openApi integration" -__url__ = "" -__download_url__ = "https://github.com/zerodhatech/pykiteconnect" +__title__ = "smartapi-python" +__description__ = "Angel Broking openApi integration" +__url__ = "https://www.angelbroking.com/" +__download_url__ = "https://github.com/angelbroking-github/smartapi-python" __version__ = "1.0.1" -__author__ = "Applied Cloud Computing Pvt ltd. (India)" -__author_email__ = "talk@zerodha.tech" -__license__ = "MIT" \ No newline at end of file +__author__ = "ab-smartapi" +__token__="ab-smartapi" +__author_email__ = "smartapi.sdk@gmail.com" +__license__ = "MIT" + +#[pypi] + # username = __token__ + # password = pypi-AgEIcHlwaS5vcmcCJDkwNzYwNzU1LWMwOTUtNGNkOC1iYjQzLTU3OWNhZjI1NDQ1MwACJXsicGVybWlzc2lvbnMiOiAidXNlciIsICJ2ZXJzaW9uIjogMX0AAAYgSpW5PAywXvchMUQnkF5H6-SolJysfUvIWopMsxE4hCM \ No newline at end of file diff --git a/build/lib/smartapi/__init__.py b/build/lib/smartapi/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/build/lib/smartapi/smartConnect.py b/build/lib/smartapi/smartConnect.py new file mode 100644 index 0000000..85602a9 --- /dev/null +++ b/build/lib/smartapi/smartConnect.py @@ -0,0 +1,353 @@ +from six.moves.urllib.parse import urljoin +import sys +sys.path.append('c:\AngelSmartApi\SmartApi') +print (sys.path) +import csv +import json +import dateutil.parser +import hashlib +import logging +import datetime +import smartExceptions +import requests +from requests import get +import re, uuid +import socket + +from version import __version__, __title__ + +log = logging.getLogger(__name__) + + +class SmartConnect(object): + _rootUrl = "https://openapisuat.angelbroking.com" + _loginUrl = "https://openapisuat.angelbroking.com/login-service/rest/auth/angelbroking/user/v1/loginByPassword" + _default_timeout = 7 # In seconds + # Products + PRODUCT_MIS = "MIS" + PRODUCT_CNC = "CNC" + PRODUCT_NRML = "NRML" + PRODUCT_CO = "CO" + PRODUCT_BO = "BO" + + # Order types + ORDER_TYPE_MARKET = "MARKET" + ORDER_TYPE_LIMIT = "LIMIT" + ORDER_TYPE_SLM = "SL-M" + ORDER_TYPE_SL = "SL" + + # Varities + VARIETY_REGULAR = "regular" + VARIETY_BO = "bo" + VARIETY_CO = "co" + VARIETY_AMO = "amo" + + # Transaction type + TRANSACTION_TYPE_BUY = "BUY" + TRANSACTION_TYPE_SELL = "SELL" + + # Validity + VALIDITY_DAY = "DAY" + VALIDITY_IOC = "IOC" + + # Exchanges + EXCHANGE_NSE = "NSE" + EXCHANGE_BSE = "BSE" + EXCHANGE_NFO = "NFO" + EXCHANGE_CDS = "CDS" + EXCHANGE_BFO = "BFO" + EXCHANGE_MCX = "MCX" + + # Status constants + STATUS_COMPLETE = "COMPLETE" + STATUS_REJECTED = "REJECTED" + STATUS_CANCELLED = "CANCELLED" + + _routes = { + "api.login":"/login-service/rest/auth/angelbroking/user/v1/loginByPassword", + "api.logout":"/login-service/rest/secure/angelbroking/user/v1/logout", + "api.token": "/login-service/rest/auth/angelbroking/jwt/v1/generateTokens", + "api.refresh": "/login-service/rest/auth/angelbroking/jwt/v1/generateTokens", + "api.user.profile": "/login-service/rest/secure/angelbroking/user/v1/getProfile", + + "api.order.place": "/order-service/rest/secure/angelbroking/order/v1/placeOrder", + "api.order.modify": "/order-service/rest/secure/angelbroking/order/v1/modifyOrder", + "api.order.cancel": "/order-service/rest/secure/angelbroking/order/v1/cancelOrder", + "api.order.book":"/order-service/rest/secure/angelbroking/order/v1/getOrderBook", + + "api.ltp.data": "/order-service/rest/secure/angelbroking/order/v1/getLtpData", + "api.trade.book": "/order-service/rest/secure/angelbroking/order/v1/getTradeBook", + "api.rms.limit": "/order-service/rest/secure/angelbroking/rms/v1/getRMS", + "api.holding": "/order-service/rest/secure/angelbroking/rms/v1/getHolding", + "api.position": "/order-service/rest/secure/angelbroking/rms/v1/getPosition", + "api.convert.position": "/order-service/rest/secure/angelbroking/rms/v1/convertPosition" + } + + def __init__(self, api_key=None, access_token=None, refresh_token=None, userId=None, root=None, debug=False, timeout=None, proxies=None, pool=None, disable_ssl=False): + self.debug = debug + self.api_key = api_key + self.session_expiry_hook = None + self.disable_ssl = disable_ssl + self.access_token = access_token + self.refresh_token = refresh_token + self.userId = userId + self.proxies = proxies if proxies else {} + self.root = root or self._loginUrl + self.timeout = timeout or self._default_timeout + + if pool: + self.reqsession = requests.Session() + reqadapter = requests.adapters.HTTPAdapter(**pool) + self.reqsession.mount("https://", reqadapter) + print("in pool") + else: + self.reqsession = requests + + # disable requests SSL warning + requests.packages.urllib3.disable_warnings() + + def setSessionExpiryHook(self, method): + if not callable(method): + raise TypeError("Invalid input type. Only functions are accepted.") + self.session_expiry_hook = method + + def getUserId(): + return userId; + + def setUserId(self,id): + self.userId=id + + def setAccessToken(self, access_token): + + self.access_token = access_token + + def setRefreshToken(self, refresh_token): + + self.refresh_token = refresh_token + + + def _request(self, route, method, parameters=None): + """Make an HTTP request.""" + params = parameters.copy() if parameters else {} + print(params) + uri =self._routes[route].format(**params) + #print(uri) + url = urljoin(self.root, uri) + print(url) + hostname = socket.gethostname() + clientLocalIP=socket.gethostbyname(hostname) + clientPublicIP=get('https://api.ipify.org').text + macAddress = ':'.join(re.findall('..', '%012x' % uuid.getnode())) + privateKey = "test" + accept = "application/json" + userType = "USER" + sourceID = "WEB" + + # Custom headers + headers = { + #"X-Kite-Version": "3", + #"User-Agent": self._user_agent(), + "Content-type":accept, + "X-ClientLocalIP": clientLocalIP, + "X-ClientPublicIP": clientPublicIP, + "X-MACAddress": macAddress, + "Accept": accept, + "X-PrivateKey": privateKey, + "X-UserType": userType, + "X-SourceID": sourceID + } + + #if self.api_key and self.access_token: + if self.access_token: + # set authorization header + print("11111111111111111",self.access_token) + auth_header = self.access_token + headers["Authorization"] = "Bearer {}".format(auth_header) + print(auth_header) + if self.debug: + log.debug("Request: {method} {url} {params} {headers}".format(method=method, url=url, params=params, headers=headers)) + print(headers) + try: + r = requests.request(method, + url, + data=json.dumps(params) if method in ["POST", "PUT"] else None, + params=json.dumps(params) if method in ["GET", "DELETE"] else None, + headers=headers, + verify=not self.disable_ssl, + allow_redirects=True, + timeout=self.timeout, + proxies=self.proxies) + print(r) + except Exception as e: + raise e + + if self.debug: + log.debug("Response: {code} {content}".format(code=r.status_code, content=r.content)) + + # Validate the content type. + if "json" in headers["Content-type"]: + try: + data = json.loads(r.content.decode("utf8")) + print("cgqkqwhxbqwxwuv",data) + except ValueError: + raise DataException("Couldn't parse the JSON response received from the server: {content}".format( + content=r.content)) + + # api error + if data.get("error_type"): + # Call session hook if its registered and TokenException is raised + if self.session_expiry_hook and r.status_code == 403 and data["error_type"] == "TokenException": + self.session_expiry_hook() + + # native Kite errors + exp = getattr(ex, data["error_type"], GeneralException) + raise exp(data["message"], code=r.status_code) + + return data + elif "csv" in headers["Content-type"]: + return r.content + else: + raise DataException("Unknown Content-type ({content_type}) with response: ({content})".format( + content_type=headers["Content-type"], + content=r.content)) + + def _deleteRequest(self, route, params=None): + """Alias for sending a DELETE request.""" + return self._request(route, "DELETE", params) + def _putRequest(self, route, params=None): + """Alias for sending a PUT request.""" + return self._request(route, "PUT", params) + def _postRequest(self, route, params=None): + """Alias for sending a POST request.""" + print("here",route,params) + return self._request(route, "POST", params) + def _getRequest(self, route, params=None): + """Alias for sending a GET request.""" + return self._request(route, "GET", params) + + def generateSession(self,clientCode,password): + print("Client Code:",clientCode,"Password:",password) + params={"clientcode":clientCode,"password":password} + loginResultObject=self._postRequest("api.login",params) + jwtToken=loginResultObject['data']['jwtToken'] + self.setAccessToken(jwtToken) + refreshToken=loginResultObject['data']['refreshToken'] + self.setRefreshToken(refreshToken) + user=self.getProfile(refreshToken) + print("User",user) + id=user['data']['clientcode'] + print(id) + self.setUserId(id) + user['data']['jwtToken']="Bearer "+jwtToken + user['data']['refreshToken']=refreshToken + return user + + def terminateSession(self,clientCode): + logoutResponseObject=self._postRequest("api.logout",{"clientcode":clientCode}) + return logoutResponseObject + + def generateToken(self,refresh_token): + response=self._postRequest('api.token',{"refreshToken":refresh_token}) + jwtToken=response['data']['jwtToken'] + self.setAccessToken(jwtToken) + return response + + def renewAccessToken(self): + + # h = hashlib.sha256(self.api_key.encode("utf-8") + refresh_token.encode("utf-8") + access_token.encode("utf-8")) + # checksum = h.hexdigest() + + response =self._postRequest('api.refresh', { + "jwtToken": self.access_token, + "refreshToken": self.refresh_token, + #"checksum": checksum + }) + print(response) + tokenSet={} + + if "jwtToken" in response: + tokenSet['jwtToken']=response['data']['jwtToken'] + tokenSet['clientcode']=self.userId + tokenSet['refreshToken']=response['data']["refreshToken"] + print(tokenSet) + return tokenSet + + def getProfile(self,refreshToken): + user=self._getRequest("api.user.profile",{"refreshToken":refreshToken}) + return user + + def placeOrder(self,orderparams): + #params = {"exchange":orderparams.exchange,"symbolToken":orderparams.symboltoken,"transactionType":orderparams.transactionType,"quantity":orderparams.quantity,"price":orderparams.price,"productType":orderparams.producttype,"orderType":orderparams.ordertype,"duration":orderparams.duration,"variety":orderparams.variety,"tradingSymbol":orderparams.tradingsymbol,"triggerPrice":orderparams.trigger_price,"squareoff":orderparams.squareoff,"stoploss":orderparams.stoploss,"trailingStoploss":orderparams.trailing_stoploss,"tag":orderparams.tag} + params=orderparams + print(params) + for k in list(params.keys()): + if params[k] is None : + del(params[k]) + + orderResponse= self._postRequest("api.order.place", params)['data']['orderid'] + print(orderResponse) + return orderResponse + + def modifyOrder(self,orderparams): + params = orderparams + + for k in list(params.keys()): + if params[k] is None: + del(params[k]) + + orderResponse= self._postRequest("api.order.modify", params) + #order=Order(orderResponse) + #order['orderId']=orderResponse['data']['orderid'] + return orderResponse + + def cancelOrder(self, order_id,variety): + orderResponse= self._postRequest("api.order.cancel", {"variety": variety,"orderid": order_id}) + return orderResponse + + def ltpData(self,exchange,tradingsymbol,symboltoken): + params={ + "exchange":exchange, + "tradingsymbol":tradingsymbol, + "symboltoken":symboltoken + } + ltpDataResponse= self._postRequest("api.ltp.data",params) + return ltpDataResponse + + def orderBook(self): + orderBookResponse=self._getRequest("api.order.book") + return orderBookResponse + + + def tradeBook(self): + tradeBookResponse=self._getRequest("api.trade.book") + return tradeBookResponse + + def rmsLimit(self): + rmsLimitResponse= self._getRequest("api.rms.limit") + return rmsLimitResponse + + def position(self): + positionResponse= self._getRequest("api.position") + return positionResponse + + def holding(self): + holdingResponse= self._getRequest("api.holding") + return holdingResponse + + def convertPosition(self,positionParams): + params=positionParams + for k in list(params.keys()): + if params[k] is None: + del(params[k]) + convertPositionResponse= self._postRequest("api.position.convert",params) + + return convertPositionResponse + + def _user_agent(self): + return (__title__ + "-python/").capitalize() + __version__ + + + + + + \ No newline at end of file diff --git a/build/lib/smartapi/smartExceptions.py b/build/lib/smartapi/smartExceptions.py new file mode 100644 index 0000000..6bf1984 --- /dev/null +++ b/build/lib/smartapi/smartExceptions.py @@ -0,0 +1,62 @@ +class SmartAPIException(Exception): + + def __init__(self, message, code=500): + """Initialize the exception.""" + super(SmartAPIException, self).__init__(message) + self.code = code + + +class GeneralException(SmartAPIException): + """An unclassified, general error. Default code is 500.""" + + def __init__(self, message, code=500): + """Initialize the exception.""" + super(GeneralException, self).__init__(message, code) + + +class TokenException(SmartAPIException): + """Represents all token and authentication related errors. Default code is 403.""" + + def __init__(self, message, code=403): + """Initialize the exception.""" + super(TokenException, self).__init__(message, code) + + +class PermissionException(SmartAPIException): + """Represents permission denied exceptions for certain calls. Default code is 403.""" + + def __init__(self, message, code=403): + """Initialize the exception.""" + super(PermissionException, self).__init__(message, code) + + +class OrderException(SmartAPIException): + """Represents all order placement and manipulation errors. Default code is 500.""" + + def __init__(self, message, code=500): + """Initialize the exception.""" + super(OrderException, self).__init__(message, code) + + +class InputException(SmartAPIException): + """Represents user input errors such as missing and invalid parameters. Default code is 400.""" + + def __init__(self, message, code=400): + """Initialize the exception.""" + super(InputException, self).__init__(message, code) + + +class DataException(SmartAPIException): + """Represents a bad response from the backend Order Management System (OMS). Default code is 502.""" + + def __init__(self, message, code=502): + """Initialize the exception.""" + super(DataException, self).__init__(message, code) + + +class NetworkException(SmartAPIException): + """Represents a network issue between Kite and the backend Order Management System (OMS). Default code is 503.""" + + def __init__(self, message, code=503): + """Initialize the exception.""" + super(NetworkException, self).__init__(message, code) diff --git a/build/lib/smartapi/version.py b/build/lib/smartapi/version.py new file mode 100644 index 0000000..a7b5a3e --- /dev/null +++ b/build/lib/smartapi/version.py @@ -0,0 +1,13 @@ +__title__ = "smartapi-python" +__description__ = "Angel Broking openApi integration" +__url__ = "https://www.angelbroking.com/" +__download_url__ = "https://github.com/angelbroking-github/smartapi-python" +__version__ = "1.0.1" +__author__ = "ab-smartapi" +__token__="ab-smartapi" +__author_email__ = "smartapi.sdk@gmail.com" +__license__ = "MIT" + +#[pypi] + # username = __token__ + # password = pypi-AgEIcHlwaS5vcmcCJDkwNzYwNzU1LWMwOTUtNGNkOC1iYjQzLTU3OWNhZjI1NDQ1MwACJXsicGVybWlzc2lvbnMiOiAidXNlciIsICJ2ZXJzaW9uIjogMX0AAAYgSpW5PAywXvchMUQnkF5H6-SolJysfUvIWopMsxE4hCM \ No newline at end of file diff --git a/dist/smartapi-python-1.0.1.tar.gz b/dist/smartapi-python-1.0.1.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..276357cc72e9830f389a89e13cc0024579d2466e GIT binary patch literal 6141 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 literal 0 HcmV?d00001 diff --git a/dist/smartapi_python-1.0.1-py3-none-any.whl b/dist/smartapi_python-1.0.1-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..6bebd2af220ca5e247d3e5096fcb342c753b7343 GIT binary patch literal 6601 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 J1=2sC{s#f7%4h%p literal 0 HcmV?d00001 diff --git a/example/sample.py b/example/sample.py new file mode 100644 index 0000000..d86d489 --- /dev/null +++ b/example/sample.py @@ -0,0 +1,17 @@ +#package import statement +from smartapi import smartConnect as sc + +#creating object of the class SmartConnect +obj=sc.SmartConnect() + +#function to call the login api + +def loginApiCall(clientcode,password): + print(clientcode,password) + loginResponse= obj.generateSession(clientcode,password) + print("Loggedin Successfully") + return loginResponse + + +print(loginApiCall('D88311','Angel@444')) + diff --git a/requirements_dev.txt b/requirements_dev.txt new file mode 100644 index 0000000..c1693f2 --- /dev/null +++ b/requirements_dev.txt @@ -0,0 +1,2 @@ +requests>=2.24.0 +twine>=1.13.0 \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..75ec875 --- /dev/null +++ b/setup.py @@ -0,0 +1,40 @@ + +from setuptools import setup, find_packages + +about={} +with open("README.md", "r") as readme_file: + readme = readme_file.read() + +requirements = [ + "requests>=2.18.4", + "six>=1.11.0", + "python-dateutil>=2.6.1" + ] + +setup( + name="smartapi-python", + version="1.0.1", + author="ab-smartapi", + author_email="smartapi.sdk@gmail.com", + description="Angel Broking openApi integration", + long_description=readme, + long_description_content_type="text/markdown", + url="https://github.com/angelbroking-github/smartapi-python", + packages=["smartapi"], + install_requires=requirements, + classifiers=[ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Intended Audience :: Financial and Insurance Industry", + "Programming Language :: Python", + "Natural Language :: English", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Topic :: Office/Business :: Financial :: Investment", + "Topic :: Software Development :: Libraries :: Python Modules", + "Topic :: Software Development :: Libraries" + ], +) \ No newline at end of file diff --git a/smartapi_python.egg-info/PKG-INFO b/smartapi_python.egg-info/PKG-INFO new file mode 100644 index 0000000..3cf8b68 --- /dev/null +++ b/smartapi_python.egg-info/PKG-INFO @@ -0,0 +1,24 @@ +Metadata-Version: 2.1 +Name: smartapi-python +Version: 1.0.1 +Summary: Angel Broking openApi integration +Home-page: https://github.com/angelbroking-github/smartapi-python +Author: ab-smartapi +Author-email: smartapi.sdk@gmail.com +License: UNKNOWN +Description: # smartapi-python +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: Intended Audience :: Financial and Insurance Industry +Classifier: Programming Language :: Python +Classifier: Natural Language :: English +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Topic :: Office/Business :: Financial :: Investment +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Software Development :: Libraries +Description-Content-Type: text/markdown diff --git a/smartapi_python.egg-info/SOURCES.txt b/smartapi_python.egg-info/SOURCES.txt new file mode 100644 index 0000000..cba6933 --- /dev/null +++ b/smartapi_python.egg-info/SOURCES.txt @@ -0,0 +1,12 @@ +README.md +setup.py +smartapi/__init__.py +smartapi/smartConnect.py +smartapi/smartExceptions.py +smartapi/version.py +smartapi_python.egg-info/PKG-INFO +smartapi_python.egg-info/SOURCES.txt +smartapi_python.egg-info/dependency_links.txt +smartapi_python.egg-info/requires.txt +smartapi_python.egg-info/top_level.txt +test/test.py \ No newline at end of file diff --git a/smartapi_python.egg-info/dependency_links.txt b/smartapi_python.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/smartapi_python.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/smartapi_python.egg-info/requires.txt b/smartapi_python.egg-info/requires.txt new file mode 100644 index 0000000..f07fa97 --- /dev/null +++ b/smartapi_python.egg-info/requires.txt @@ -0,0 +1,3 @@ +requests>=2.18.4 +six>=1.11.0 +python-dateutil>=2.6.1 diff --git a/smartapi_python.egg-info/top_level.txt b/smartapi_python.egg-info/top_level.txt new file mode 100644 index 0000000..35c4703 --- /dev/null +++ b/smartapi_python.egg-info/top_level.txt @@ -0,0 +1 @@ +smartapi From 45278933d0ce16e303ace109d5cce0d9781f46f8 Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Mon, 9 Nov 2020 15:24:09 +0530 Subject: [PATCH 03/49] Elemination of few unwanted keywords --- .../smartExceptions.cpython-36.pyc | Bin 3678 -> 3677 bytes SmartApi/__pycache__/version.cpython-36.pyc | Bin 480 -> 480 bytes SmartApi/smartConnect.py | 74 ++-- SmartApi/smartExceptions.py | 2 +- SmartApi/version.py | 8 +- build/lib/smartapi/__init__.py | 0 build/lib/smartapi/smartConnect.py | 353 ------------------ build/lib/smartapi/smartExceptions.py | 62 --- build/lib/smartapi/version.py | 13 - dist/smartapi-python-1.0.1.tar.gz | Bin 6141 -> 0 bytes dist/smartapi_python-1.0.1-py3-none-any.whl | Bin 6601 -> 0 bytes example/sample.py | 20 +- smartapi_python.egg-info/PKG-INFO | 24 -- smartapi_python.egg-info/SOURCES.txt | 12 - smartapi_python.egg-info/dependency_links.txt | 1 - smartapi_python.egg-info/requires.txt | 3 - smartapi_python.egg-info/top_level.txt | 1 - test/test.py | 55 +-- 18 files changed, 78 insertions(+), 550 deletions(-) delete mode 100644 build/lib/smartapi/__init__.py delete mode 100644 build/lib/smartapi/smartConnect.py delete mode 100644 build/lib/smartapi/smartExceptions.py delete mode 100644 build/lib/smartapi/version.py delete mode 100644 dist/smartapi-python-1.0.1.tar.gz delete mode 100644 dist/smartapi_python-1.0.1-py3-none-any.whl delete mode 100644 smartapi_python.egg-info/PKG-INFO delete mode 100644 smartapi_python.egg-info/SOURCES.txt delete mode 100644 smartapi_python.egg-info/dependency_links.txt delete mode 100644 smartapi_python.egg-info/requires.txt delete mode 100644 smartapi_python.egg-info/top_level.txt diff --git a/SmartApi/__pycache__/smartExceptions.cpython-36.pyc b/SmartApi/__pycache__/smartExceptions.cpython-36.pyc index 51d0a35e45c686acb867576996fe6679f2483f1e..8f9b5aa985bb0e1a1e0bb9b191002e1c45efda26 100644 GIT binary patch delta 41 xcmca7b61Abn3tDpDeKDkeH%F|c^I=MH}fd7Cl+KXB<7_|e$QpM`3+AIBLE*~4le)z delta 42 ycmcaBb5DlTn3tDJS#Dzd{*9cKJdD|sn|YKuyfaHu6%zAOCco#h+x(iRh!FrBRt^II diff --git a/SmartApi/__pycache__/version.cpython-36.pyc b/SmartApi/__pycache__/version.cpython-36.pyc index 6aaf2ef211964cbff76088ad4f5a9f8196158c70..289b8a749518b7cceada335149ee19d1674de2b2 100644 GIT binary patch delta 18 ZcmaFB{D7I$n3tDpE7Qt&+l`#p838rh1+@SG delta 18 ZcmaFB{D7I$n3tD}jcsPU)ke{ diff --git a/SmartApi/smartConnect.py b/SmartApi/smartConnect.py index a753e0c..1c9cfae 100644 --- a/SmartApi/smartConnect.py +++ b/SmartApi/smartConnect.py @@ -1,5 +1,6 @@ from six.moves.urllib.parse import urljoin import sys + sys.path.append('c:\AngelSmartApi\SmartApi') import csv import json @@ -7,13 +8,13 @@ import hashlib import logging import datetime -import smartExceptions +import smartapi.smartExceptions as ex import requests from requests import get import re, uuid import socket -from version import __version__, __title__ +from smartapi.version import __version__, __title__ log = logging.getLogger(__name__) @@ -128,9 +129,11 @@ def setRefreshToken(self, refresh_token): def _request(self, route, method, parameters=None): """Make an HTTP request.""" params = parameters.copy() if parameters else {} - print("Request params:",params) + uri =self._routes[route].format(**params) + #print(uri) url = urljoin(self.root, uri) + hostname = socket.gethostname() clientLocalIP=socket.gethostbyname(hostname) clientPublicIP=get('https://api.ipify.org').text @@ -142,8 +145,8 @@ def _request(self, route, method, parameters=None): # Custom headers headers = { - #"X-Kite-Version": "3", - #"User-Agent": self._user_agent(), + #"X-SmartApi-Version": "", + #"User-Agent": self._user_agent() "Content-type":accept, "X-ClientLocalIP": clientLocalIP, "X-ClientPublicIP": clientPublicIP, @@ -157,12 +160,13 @@ def _request(self, route, method, parameters=None): #if self.api_key and self.access_token: if self.access_token: # set authorization header - + auth_header = self.access_token headers["Authorization"] = "Bearer {}".format(auth_header) + if self.debug: log.debug("Request: {method} {url} {params} {headers}".format(method=method, url=url, params=params, headers=headers)) - + try: r = requests.request(method, url, @@ -184,9 +188,9 @@ def _request(self, route, method, parameters=None): if "json" in headers["Content-type"]: try: data = json.loads(r.content.decode("utf8")) - print("The Reponse Content",data) + except ValueError: - raise DataException("Couldn't parse the JSON response received from the server: {content}".format( + raise ex.DataException("Couldn't parse the JSON response received from the server: {content}".format( content=r.content)) # api error @@ -195,15 +199,15 @@ def _request(self, route, method, parameters=None): if self.session_expiry_hook and r.status_code == 403 and data["error_type"] == "TokenException": self.session_expiry_hook() - # native Kite errors - exp = getattr(ex, data["error_type"], GeneralException) + # native errors + exp = getattr(ex, data["error_type"], ex.GeneralException) raise exp(data["message"], code=r.status_code) return data elif "csv" in headers["Content-type"]: return r.content else: - raise DataException("Unknown Content-type ({content_type}) with response: ({content})".format( + raise ex.DataException("Unknown Content-type ({content_type}) with response: ({content})".format( content_type=headers["Content-type"], content=r.content)) @@ -215,34 +219,29 @@ def _putRequest(self, route, params=None): return self._request(route, "PUT", params) def _postRequest(self, route, params=None): """Alias for sending a POST request.""" - print("here",route,params) return self._request(route, "POST", params) def _getRequest(self, route, params=None): """Alias for sending a GET request.""" return self._request(route, "GET", params) def generateSession(self,clientCode,password): - print("Client Code:",clientCode,"Password:",password) + params={"clientcode":clientCode,"password":password} loginResultObject=self._postRequest("api.login",params) - if "jwtToken" and "refreshToken" in loginResultObject: - jwtToken=loginResultObject['data']['jwtToken'] - refreshToken=loginResultObject['data']['refreshToken'] - self.setAccessToken(jwtToken) - self.setRefreshToken(refreshToken) - user=self.getProfile(refreshToken) - print("User",user) - id=user['data']['clientcode'] - print(id) - self.setUserId(id) - user['data']['jwtToken']="Bearer "+jwtToken - user['data']['refreshToken']=refreshToken - return user - - else: - print("Password or Userid is incorrect or expired") - + jwtToken=loginResultObject['data']['jwtToken'] + self.setAccessToken(jwtToken) + refreshToken=loginResultObject['data']['refreshToken'] + self.setRefreshToken(refreshToken) + user=self.getProfile(refreshToken) + + id=user['data']['clientcode'] + + print(id) + self.setUserId(id) + user['data']['jwtToken']="Bearer "+jwtToken + user['data']['refreshToken']=refreshToken + return user def terminateSession(self,clientCode): logoutResponseObject=self._postRequest("api.logout",{"clientcode":clientCode}) @@ -264,14 +263,14 @@ def renewAccessToken(self): "refreshToken": self.refresh_token, #"checksum": checksum }) - + tokenSet={} if "jwtToken" in response: tokenSet['jwtToken']=response['data']['jwtToken'] tokenSet['clientcode']=self.userId tokenSet['refreshToken']=response['data']["refreshToken"] - print(tokenSet) + return tokenSet def getProfile(self,refreshToken): @@ -281,13 +280,13 @@ def getProfile(self,refreshToken): def placeOrder(self,orderparams): #params = {"exchange":orderparams.exchange,"symbolToken":orderparams.symboltoken,"transactionType":orderparams.transactionType,"quantity":orderparams.quantity,"price":orderparams.price,"productType":orderparams.producttype,"orderType":orderparams.ordertype,"duration":orderparams.duration,"variety":orderparams.variety,"tradingSymbol":orderparams.tradingsymbol,"triggerPrice":orderparams.trigger_price,"squareoff":orderparams.squareoff,"stoploss":orderparams.stoploss,"trailingStoploss":orderparams.trailing_stoploss,"tag":orderparams.tag} params=orderparams - print("placeOrder params",params) + for k in list(params.keys()): if params[k] is None : del(params[k]) orderResponse= self._postRequest("api.order.place", params)['data']['orderid'] - print("The placeOrder",orderResponse) + return orderResponse def modifyOrder(self,orderparams): @@ -348,8 +347,3 @@ def convertPosition(self,positionParams): def _user_agent(self): return (__title__ + "-python/").capitalize() + __version__ - - - - - \ No newline at end of file diff --git a/SmartApi/smartExceptions.py b/SmartApi/smartExceptions.py index 6bf1984..b9f2561 100644 --- a/SmartApi/smartExceptions.py +++ b/SmartApi/smartExceptions.py @@ -55,7 +55,7 @@ def __init__(self, message, code=502): class NetworkException(SmartAPIException): - """Represents a network issue between Kite and the backend Order Management System (OMS). Default code is 503.""" + """Represents a network issue between api and the backend Order Management System (OMS). Default code is 503.""" def __init__(self, message, code=503): """Initialize the exception.""" diff --git a/SmartApi/version.py b/SmartApi/version.py index a7b5a3e..6549f56 100644 --- a/SmartApi/version.py +++ b/SmartApi/version.py @@ -4,10 +4,10 @@ __download_url__ = "https://github.com/angelbroking-github/smartapi-python" __version__ = "1.0.1" __author__ = "ab-smartapi" -__token__="ab-smartapi" +__token__ = "ab-smartapi" __author_email__ = "smartapi.sdk@gmail.com" __license__ = "MIT" -#[pypi] - # username = __token__ - # password = pypi-AgEIcHlwaS5vcmcCJDkwNzYwNzU1LWMwOTUtNGNkOC1iYjQzLTU3OWNhZjI1NDQ1MwACJXsicGVybWlzc2lvbnMiOiAidXNlciIsICJ2ZXJzaW9uIjogMX0AAAYgSpW5PAywXvchMUQnkF5H6-SolJysfUvIWopMsxE4hCM \ No newline at end of file +# [pypi] +# username = __token__ +# password = pypi-AgEIcHlwaS5vcmcCJDkwNzYwNzU1LWMwOTUtNGNkOC1iYjQzLTU3OWNhZjI1NDQ1MwACJXsicGVybWlzc2lvbnMiOiAidXNlciIsICJ2ZXJzaW9uIjogMX0AAAYgSpW5PAywXvchMUQnkF5H6-SolJysfUvIWopMsxE4hCM diff --git a/build/lib/smartapi/__init__.py b/build/lib/smartapi/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/build/lib/smartapi/smartConnect.py b/build/lib/smartapi/smartConnect.py deleted file mode 100644 index 85602a9..0000000 --- a/build/lib/smartapi/smartConnect.py +++ /dev/null @@ -1,353 +0,0 @@ -from six.moves.urllib.parse import urljoin -import sys -sys.path.append('c:\AngelSmartApi\SmartApi') -print (sys.path) -import csv -import json -import dateutil.parser -import hashlib -import logging -import datetime -import smartExceptions -import requests -from requests import get -import re, uuid -import socket - -from version import __version__, __title__ - -log = logging.getLogger(__name__) - - -class SmartConnect(object): - _rootUrl = "https://openapisuat.angelbroking.com" - _loginUrl = "https://openapisuat.angelbroking.com/login-service/rest/auth/angelbroking/user/v1/loginByPassword" - _default_timeout = 7 # In seconds - # Products - PRODUCT_MIS = "MIS" - PRODUCT_CNC = "CNC" - PRODUCT_NRML = "NRML" - PRODUCT_CO = "CO" - PRODUCT_BO = "BO" - - # Order types - ORDER_TYPE_MARKET = "MARKET" - ORDER_TYPE_LIMIT = "LIMIT" - ORDER_TYPE_SLM = "SL-M" - ORDER_TYPE_SL = "SL" - - # Varities - VARIETY_REGULAR = "regular" - VARIETY_BO = "bo" - VARIETY_CO = "co" - VARIETY_AMO = "amo" - - # Transaction type - TRANSACTION_TYPE_BUY = "BUY" - TRANSACTION_TYPE_SELL = "SELL" - - # Validity - VALIDITY_DAY = "DAY" - VALIDITY_IOC = "IOC" - - # Exchanges - EXCHANGE_NSE = "NSE" - EXCHANGE_BSE = "BSE" - EXCHANGE_NFO = "NFO" - EXCHANGE_CDS = "CDS" - EXCHANGE_BFO = "BFO" - EXCHANGE_MCX = "MCX" - - # Status constants - STATUS_COMPLETE = "COMPLETE" - STATUS_REJECTED = "REJECTED" - STATUS_CANCELLED = "CANCELLED" - - _routes = { - "api.login":"/login-service/rest/auth/angelbroking/user/v1/loginByPassword", - "api.logout":"/login-service/rest/secure/angelbroking/user/v1/logout", - "api.token": "/login-service/rest/auth/angelbroking/jwt/v1/generateTokens", - "api.refresh": "/login-service/rest/auth/angelbroking/jwt/v1/generateTokens", - "api.user.profile": "/login-service/rest/secure/angelbroking/user/v1/getProfile", - - "api.order.place": "/order-service/rest/secure/angelbroking/order/v1/placeOrder", - "api.order.modify": "/order-service/rest/secure/angelbroking/order/v1/modifyOrder", - "api.order.cancel": "/order-service/rest/secure/angelbroking/order/v1/cancelOrder", - "api.order.book":"/order-service/rest/secure/angelbroking/order/v1/getOrderBook", - - "api.ltp.data": "/order-service/rest/secure/angelbroking/order/v1/getLtpData", - "api.trade.book": "/order-service/rest/secure/angelbroking/order/v1/getTradeBook", - "api.rms.limit": "/order-service/rest/secure/angelbroking/rms/v1/getRMS", - "api.holding": "/order-service/rest/secure/angelbroking/rms/v1/getHolding", - "api.position": "/order-service/rest/secure/angelbroking/rms/v1/getPosition", - "api.convert.position": "/order-service/rest/secure/angelbroking/rms/v1/convertPosition" - } - - def __init__(self, api_key=None, access_token=None, refresh_token=None, userId=None, root=None, debug=False, timeout=None, proxies=None, pool=None, disable_ssl=False): - self.debug = debug - self.api_key = api_key - self.session_expiry_hook = None - self.disable_ssl = disable_ssl - self.access_token = access_token - self.refresh_token = refresh_token - self.userId = userId - self.proxies = proxies if proxies else {} - self.root = root or self._loginUrl - self.timeout = timeout or self._default_timeout - - if pool: - self.reqsession = requests.Session() - reqadapter = requests.adapters.HTTPAdapter(**pool) - self.reqsession.mount("https://", reqadapter) - print("in pool") - else: - self.reqsession = requests - - # disable requests SSL warning - requests.packages.urllib3.disable_warnings() - - def setSessionExpiryHook(self, method): - if not callable(method): - raise TypeError("Invalid input type. Only functions are accepted.") - self.session_expiry_hook = method - - def getUserId(): - return userId; - - def setUserId(self,id): - self.userId=id - - def setAccessToken(self, access_token): - - self.access_token = access_token - - def setRefreshToken(self, refresh_token): - - self.refresh_token = refresh_token - - - def _request(self, route, method, parameters=None): - """Make an HTTP request.""" - params = parameters.copy() if parameters else {} - print(params) - uri =self._routes[route].format(**params) - #print(uri) - url = urljoin(self.root, uri) - print(url) - hostname = socket.gethostname() - clientLocalIP=socket.gethostbyname(hostname) - clientPublicIP=get('https://api.ipify.org').text - macAddress = ':'.join(re.findall('..', '%012x' % uuid.getnode())) - privateKey = "test" - accept = "application/json" - userType = "USER" - sourceID = "WEB" - - # Custom headers - headers = { - #"X-Kite-Version": "3", - #"User-Agent": self._user_agent(), - "Content-type":accept, - "X-ClientLocalIP": clientLocalIP, - "X-ClientPublicIP": clientPublicIP, - "X-MACAddress": macAddress, - "Accept": accept, - "X-PrivateKey": privateKey, - "X-UserType": userType, - "X-SourceID": sourceID - } - - #if self.api_key and self.access_token: - if self.access_token: - # set authorization header - print("11111111111111111",self.access_token) - auth_header = self.access_token - headers["Authorization"] = "Bearer {}".format(auth_header) - print(auth_header) - if self.debug: - log.debug("Request: {method} {url} {params} {headers}".format(method=method, url=url, params=params, headers=headers)) - print(headers) - try: - r = requests.request(method, - url, - data=json.dumps(params) if method in ["POST", "PUT"] else None, - params=json.dumps(params) if method in ["GET", "DELETE"] else None, - headers=headers, - verify=not self.disable_ssl, - allow_redirects=True, - timeout=self.timeout, - proxies=self.proxies) - print(r) - except Exception as e: - raise e - - if self.debug: - log.debug("Response: {code} {content}".format(code=r.status_code, content=r.content)) - - # Validate the content type. - if "json" in headers["Content-type"]: - try: - data = json.loads(r.content.decode("utf8")) - print("cgqkqwhxbqwxwuv",data) - except ValueError: - raise DataException("Couldn't parse the JSON response received from the server: {content}".format( - content=r.content)) - - # api error - if data.get("error_type"): - # Call session hook if its registered and TokenException is raised - if self.session_expiry_hook and r.status_code == 403 and data["error_type"] == "TokenException": - self.session_expiry_hook() - - # native Kite errors - exp = getattr(ex, data["error_type"], GeneralException) - raise exp(data["message"], code=r.status_code) - - return data - elif "csv" in headers["Content-type"]: - return r.content - else: - raise DataException("Unknown Content-type ({content_type}) with response: ({content})".format( - content_type=headers["Content-type"], - content=r.content)) - - def _deleteRequest(self, route, params=None): - """Alias for sending a DELETE request.""" - return self._request(route, "DELETE", params) - def _putRequest(self, route, params=None): - """Alias for sending a PUT request.""" - return self._request(route, "PUT", params) - def _postRequest(self, route, params=None): - """Alias for sending a POST request.""" - print("here",route,params) - return self._request(route, "POST", params) - def _getRequest(self, route, params=None): - """Alias for sending a GET request.""" - return self._request(route, "GET", params) - - def generateSession(self,clientCode,password): - print("Client Code:",clientCode,"Password:",password) - params={"clientcode":clientCode,"password":password} - loginResultObject=self._postRequest("api.login",params) - jwtToken=loginResultObject['data']['jwtToken'] - self.setAccessToken(jwtToken) - refreshToken=loginResultObject['data']['refreshToken'] - self.setRefreshToken(refreshToken) - user=self.getProfile(refreshToken) - print("User",user) - id=user['data']['clientcode'] - print(id) - self.setUserId(id) - user['data']['jwtToken']="Bearer "+jwtToken - user['data']['refreshToken']=refreshToken - return user - - def terminateSession(self,clientCode): - logoutResponseObject=self._postRequest("api.logout",{"clientcode":clientCode}) - return logoutResponseObject - - def generateToken(self,refresh_token): - response=self._postRequest('api.token',{"refreshToken":refresh_token}) - jwtToken=response['data']['jwtToken'] - self.setAccessToken(jwtToken) - return response - - def renewAccessToken(self): - - # h = hashlib.sha256(self.api_key.encode("utf-8") + refresh_token.encode("utf-8") + access_token.encode("utf-8")) - # checksum = h.hexdigest() - - response =self._postRequest('api.refresh', { - "jwtToken": self.access_token, - "refreshToken": self.refresh_token, - #"checksum": checksum - }) - print(response) - tokenSet={} - - if "jwtToken" in response: - tokenSet['jwtToken']=response['data']['jwtToken'] - tokenSet['clientcode']=self.userId - tokenSet['refreshToken']=response['data']["refreshToken"] - print(tokenSet) - return tokenSet - - def getProfile(self,refreshToken): - user=self._getRequest("api.user.profile",{"refreshToken":refreshToken}) - return user - - def placeOrder(self,orderparams): - #params = {"exchange":orderparams.exchange,"symbolToken":orderparams.symboltoken,"transactionType":orderparams.transactionType,"quantity":orderparams.quantity,"price":orderparams.price,"productType":orderparams.producttype,"orderType":orderparams.ordertype,"duration":orderparams.duration,"variety":orderparams.variety,"tradingSymbol":orderparams.tradingsymbol,"triggerPrice":orderparams.trigger_price,"squareoff":orderparams.squareoff,"stoploss":orderparams.stoploss,"trailingStoploss":orderparams.trailing_stoploss,"tag":orderparams.tag} - params=orderparams - print(params) - for k in list(params.keys()): - if params[k] is None : - del(params[k]) - - orderResponse= self._postRequest("api.order.place", params)['data']['orderid'] - print(orderResponse) - return orderResponse - - def modifyOrder(self,orderparams): - params = orderparams - - for k in list(params.keys()): - if params[k] is None: - del(params[k]) - - orderResponse= self._postRequest("api.order.modify", params) - #order=Order(orderResponse) - #order['orderId']=orderResponse['data']['orderid'] - return orderResponse - - def cancelOrder(self, order_id,variety): - orderResponse= self._postRequest("api.order.cancel", {"variety": variety,"orderid": order_id}) - return orderResponse - - def ltpData(self,exchange,tradingsymbol,symboltoken): - params={ - "exchange":exchange, - "tradingsymbol":tradingsymbol, - "symboltoken":symboltoken - } - ltpDataResponse= self._postRequest("api.ltp.data",params) - return ltpDataResponse - - def orderBook(self): - orderBookResponse=self._getRequest("api.order.book") - return orderBookResponse - - - def tradeBook(self): - tradeBookResponse=self._getRequest("api.trade.book") - return tradeBookResponse - - def rmsLimit(self): - rmsLimitResponse= self._getRequest("api.rms.limit") - return rmsLimitResponse - - def position(self): - positionResponse= self._getRequest("api.position") - return positionResponse - - def holding(self): - holdingResponse= self._getRequest("api.holding") - return holdingResponse - - def convertPosition(self,positionParams): - params=positionParams - for k in list(params.keys()): - if params[k] is None: - del(params[k]) - convertPositionResponse= self._postRequest("api.position.convert",params) - - return convertPositionResponse - - def _user_agent(self): - return (__title__ + "-python/").capitalize() + __version__ - - - - - - \ No newline at end of file diff --git a/build/lib/smartapi/smartExceptions.py b/build/lib/smartapi/smartExceptions.py deleted file mode 100644 index 6bf1984..0000000 --- a/build/lib/smartapi/smartExceptions.py +++ /dev/null @@ -1,62 +0,0 @@ -class SmartAPIException(Exception): - - def __init__(self, message, code=500): - """Initialize the exception.""" - super(SmartAPIException, self).__init__(message) - self.code = code - - -class GeneralException(SmartAPIException): - """An unclassified, general error. Default code is 500.""" - - def __init__(self, message, code=500): - """Initialize the exception.""" - super(GeneralException, self).__init__(message, code) - - -class TokenException(SmartAPIException): - """Represents all token and authentication related errors. Default code is 403.""" - - def __init__(self, message, code=403): - """Initialize the exception.""" - super(TokenException, self).__init__(message, code) - - -class PermissionException(SmartAPIException): - """Represents permission denied exceptions for certain calls. Default code is 403.""" - - def __init__(self, message, code=403): - """Initialize the exception.""" - super(PermissionException, self).__init__(message, code) - - -class OrderException(SmartAPIException): - """Represents all order placement and manipulation errors. Default code is 500.""" - - def __init__(self, message, code=500): - """Initialize the exception.""" - super(OrderException, self).__init__(message, code) - - -class InputException(SmartAPIException): - """Represents user input errors such as missing and invalid parameters. Default code is 400.""" - - def __init__(self, message, code=400): - """Initialize the exception.""" - super(InputException, self).__init__(message, code) - - -class DataException(SmartAPIException): - """Represents a bad response from the backend Order Management System (OMS). Default code is 502.""" - - def __init__(self, message, code=502): - """Initialize the exception.""" - super(DataException, self).__init__(message, code) - - -class NetworkException(SmartAPIException): - """Represents a network issue between Kite and the backend Order Management System (OMS). Default code is 503.""" - - def __init__(self, message, code=503): - """Initialize the exception.""" - super(NetworkException, self).__init__(message, code) diff --git a/build/lib/smartapi/version.py b/build/lib/smartapi/version.py deleted file mode 100644 index a7b5a3e..0000000 --- a/build/lib/smartapi/version.py +++ /dev/null @@ -1,13 +0,0 @@ -__title__ = "smartapi-python" -__description__ = "Angel Broking openApi integration" -__url__ = "https://www.angelbroking.com/" -__download_url__ = "https://github.com/angelbroking-github/smartapi-python" -__version__ = "1.0.1" -__author__ = "ab-smartapi" -__token__="ab-smartapi" -__author_email__ = "smartapi.sdk@gmail.com" -__license__ = "MIT" - -#[pypi] - # username = __token__ - # password = pypi-AgEIcHlwaS5vcmcCJDkwNzYwNzU1LWMwOTUtNGNkOC1iYjQzLTU3OWNhZjI1NDQ1MwACJXsicGVybWlzc2lvbnMiOiAidXNlciIsICJ2ZXJzaW9uIjogMX0AAAYgSpW5PAywXvchMUQnkF5H6-SolJysfUvIWopMsxE4hCM \ No newline at end of file diff --git a/dist/smartapi-python-1.0.1.tar.gz b/dist/smartapi-python-1.0.1.tar.gz deleted file mode 100644 index 276357cc72e9830f389a89e13cc0024579d2466e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6141 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 diff --git a/dist/smartapi_python-1.0.1-py3-none-any.whl b/dist/smartapi_python-1.0.1-py3-none-any.whl deleted file mode 100644 index 6bebd2af220ca5e247d3e5096fcb342c753b7343..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6601 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 J1=2sC{s#f7%4h%p diff --git a/example/sample.py b/example/sample.py index d86d489..bbf030f 100644 --- a/example/sample.py +++ b/example/sample.py @@ -1,17 +1,17 @@ -#package import statement +# package import statement from smartapi import smartConnect as sc -#creating object of the class SmartConnect -obj=sc.SmartConnect() +# creating object of the class SmartConnect +obj = sc.SmartConnect() -#function to call the login api -def loginApiCall(clientcode,password): - print(clientcode,password) - loginResponse= obj.generateSession(clientcode,password) - print("Loggedin Successfully") - return loginResponse +# function to call the login api +def loginApiCall(clientcode, password): + print(clientcode, password) + login_response = obj.generateSession(clientcode, password) + print("Logged in Successfully") + return login_response -print(loginApiCall('D88311','Angel@444')) +print(loginApiCall('D88311', 'Angel@444')) diff --git a/smartapi_python.egg-info/PKG-INFO b/smartapi_python.egg-info/PKG-INFO deleted file mode 100644 index 3cf8b68..0000000 --- a/smartapi_python.egg-info/PKG-INFO +++ /dev/null @@ -1,24 +0,0 @@ -Metadata-Version: 2.1 -Name: smartapi-python -Version: 1.0.1 -Summary: Angel Broking openApi integration -Home-page: https://github.com/angelbroking-github/smartapi-python -Author: ab-smartapi -Author-email: smartapi.sdk@gmail.com -License: UNKNOWN -Description: # smartapi-python -Platform: UNKNOWN -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: Intended Audience :: Financial and Insurance Industry -Classifier: Programming Language :: Python -Classifier: Natural Language :: English -Classifier: License :: OSI Approved :: MIT License -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3.5 -Classifier: Programming Language :: Python :: 3.6 -Classifier: Programming Language :: Python :: 3.7 -Classifier: Topic :: Office/Business :: Financial :: Investment -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Classifier: Topic :: Software Development :: Libraries -Description-Content-Type: text/markdown diff --git a/smartapi_python.egg-info/SOURCES.txt b/smartapi_python.egg-info/SOURCES.txt deleted file mode 100644 index cba6933..0000000 --- a/smartapi_python.egg-info/SOURCES.txt +++ /dev/null @@ -1,12 +0,0 @@ -README.md -setup.py -smartapi/__init__.py -smartapi/smartConnect.py -smartapi/smartExceptions.py -smartapi/version.py -smartapi_python.egg-info/PKG-INFO -smartapi_python.egg-info/SOURCES.txt -smartapi_python.egg-info/dependency_links.txt -smartapi_python.egg-info/requires.txt -smartapi_python.egg-info/top_level.txt -test/test.py \ No newline at end of file diff --git a/smartapi_python.egg-info/dependency_links.txt b/smartapi_python.egg-info/dependency_links.txt deleted file mode 100644 index 8b13789..0000000 --- a/smartapi_python.egg-info/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/smartapi_python.egg-info/requires.txt b/smartapi_python.egg-info/requires.txt deleted file mode 100644 index f07fa97..0000000 --- a/smartapi_python.egg-info/requires.txt +++ /dev/null @@ -1,3 +0,0 @@ -requests>=2.18.4 -six>=1.11.0 -python-dateutil>=2.6.1 diff --git a/smartapi_python.egg-info/top_level.txt b/smartapi_python.egg-info/top_level.txt deleted file mode 100644 index 35c4703..0000000 --- a/smartapi_python.egg-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -smartapi diff --git a/test/test.py b/test/test.py index da8e9f9..b6de560 100644 --- a/test/test.py +++ b/test/test.py @@ -1,19 +1,22 @@ import sys import os -dir=os.getcwd() -print(dir) -#path=dir.split("\") -sys.path.append(dir+"\SmartApi") -print(sys.path) -import smartConnect -smartApi=smartConnect.SmartConnect() +dir = os.getcwd() +#print(dir) +# path=dir.split("\") -login=smartApi.generateSession('D88311','Angel@444') -refreshToken=login['data']['refreshToken'] +sys.path.append(dir + "\SmartApi") +#print(sys.path) + +import smartapi.smartConnect + +smartApi = smartapi.smartConnect.SmartConnect() + +login = smartApi.generateSession('D88311', 'Angel@444') +refreshToken = login['data']['refreshToken'] smartApi.getProfile(refreshToken) smartApi.generateToken(refreshToken) -orderparams={ +orderparams = { "variety": "NORMAL", "tradingsymbol": "SBIN-EQ", "symboltoken": "3045", @@ -27,28 +30,28 @@ "stoploss": "0", "quantity": "1" } -orderid=smartApi.placeOrder(orderparams) - -modifyparams={ - "variety":"NORMAL", - "orderid":orderid, - "ordertype":"LIMIT", - "producttype":"INTRADAY", - "duration":"DAY", - "price":"19500", - "quantity":"1" +orderid = smartApi.placeOrder(orderparams) + +modifyparams = { + "variety": "NORMAL", + "orderid": orderid, + "ordertype": "LIMIT", + "producttype": "INTRADAY", + "duration": "DAY", + "price": "19500", + "quantity": "1" } smartApi.modifyOrder(modifyparams) -smartApi.cancelOrder(orderid,"NORMAL") +smartApi.cancelOrder(orderid, "NORMAL") smartApi.orderBook() smartApi.tradeBook() smartApi.rmsLimit() smartApi.position() smartApi.holding() -exchange="NSE" -tradingsymbol="SBIN-EQ" -symboltoken=3045 -smartApi.ltpData("NSE","SBIN-EQ","3045" ) -smartApi.terminateSession(login['data']['clientcode']) \ No newline at end of file +exchange = "NSE" +tradingsymbol = "SBIN-EQ" +symboltoken = 3045 +smartApi.ltpData("NSE", "SBIN-EQ", "3045") +smartApi.terminateSession(login['data']['clientcode']) From 971f9db6dcde5f44665a4523167f1d29bb74743f Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Mon, 23 Nov 2020 10:04:28 +0530 Subject: [PATCH 04/49] Websocket and README File Added, Endpoints of api changed --- README.md | 62 +++- SmartApi/__init__.py | 4 + .../__pycache__/smartConnect.cpython-36.pyc | Bin 10834 -> 10813 bytes SmartApi/__pycache__/socket.cpython-36.pyc | Bin 0 -> 141 bytes SmartApi/__pycache__/socketTP.cpython-36.pyc | Bin 0 -> 8986 bytes SmartApi/smartConnect.py | 52 +-- SmartApi/smartSocket.py | 80 +++++ SmartApi/socket1.py | 32 ++ SmartApi/socketTP.py | 301 ++++++++++++++++++ example/sample.py | 44 ++- test/test.py | 139 +++++--- 11 files changed, 629 insertions(+), 85 deletions(-) create mode 100644 SmartApi/__pycache__/socket.cpython-36.pyc create mode 100644 SmartApi/__pycache__/socketTP.cpython-36.pyc create mode 100644 SmartApi/smartSocket.py create mode 100644 SmartApi/socket1.py create mode 100644 SmartApi/socketTP.py diff --git a/README.md b/README.md index 817e2f0..c2807f8 100644 --- a/README.md +++ b/README.md @@ -1 +1,61 @@ -# smartapi-python \ No newline at end of file +# SMARTAPI-PYTHON + +SMARTAPI-PYTHON is a Python library for dealing AMX,that is a set of REST-like HTTP APIs that expose many capabilities required to build stock market investment and trading platforms. It lets you execute orders in real time. + +## Installation + +Use the package manager [pip](https://pip.pypa.io/en/stable/) to install smartapi-python. + +```bash +pip install smartapi-python +``` + +## Usage + +```python +# package import statement +from smartapi.smartConnect import SmartConnect + +#create object of call +obj=SmartConnect() + +#login api call + +data = obj.generateSession("D88311","Angel@444") +refreshToken= data['data']['refreshToken'] + +#fetch User Profile +userProfile= obj.getProfile(refreshToken) +#place order +try: + orderparams = { + "variety": "NORMAL", + "tradingsymbol": "SBIN-EQ", + "symboltoken": "3045", + "transactiontype": "BUY", + "exchange": "NSE", + "ordertype": "LIMIT", + "producttype": "INTRADAY", + "duration": "DAY", + "price": "19500", + "squareoff": "0", + "stoploss": "0", + "quantity": "1" + } + orderId=obj.placeOrder(orderparams) + print("The order id is: {}".format(orderId)) +except Exception as e: + print("Order placement failed: {}".format(e.message)) + +#logout +try: + logout=obj.terminateSession('D88311') + print("Logout Successfull") +except Exception as e: + print("Logout failed: {}".format(e.message)) + + +License +MIT + + diff --git a/SmartApi/__init__.py b/SmartApi/__init__.py index e69de29..fd40910 100644 --- a/SmartApi/__init__.py +++ b/SmartApi/__init__.py @@ -0,0 +1,4 @@ + + + + diff --git a/SmartApi/__pycache__/smartConnect.cpython-36.pyc b/SmartApi/__pycache__/smartConnect.cpython-36.pyc index 00ec287a665bf091d2fe9957b3f1c4835ce8c4ac..3f5e4801c3d97d04318920e21ff166084da359ad 100644 GIT binary patch delta 3448 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 EUq#zImH+?% delta 3730 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 Kj6j{mATt5^8X|)L literal 0 HcmV?d00001 diff --git a/SmartApi/__pycache__/socketTP.cpython-36.pyc b/SmartApi/__pycache__/socketTP.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5217bd29d30dc3914a970c61cba06bf68ab235a4 GIT binary patch literal 8986 zcmb_i&vV;We#bA8AV|rQEK9Nz+pyy#=I)w~;~$%3T(4DGUZ+W9)l$|m>Ma7|K@unu zpdUcXV#!Ws<(-{&Cfgi3oleIy?Wr^EslDuB+fz^Nt*0JvY%kTnu$T7peGjB4S)24w zaqxW)?>#)c@9!Vb^@#~<@XxpMm~eT**HGFomft#gVP*sN!C8G|}pg zE?UDeL|bqQqAfZ_(UzPNTCHWaO~+Je54}}xTaMMPI2Cbkw5sh1XHxVFtrP7jXR1Bz zOt)v88CChQ!iuc)QemZFYEO4g;@)Is+?RuC+|T0PVinw1f>XGkW9phxtM22}%1TYm zOy;FQ8n%O)mX&zm`Dx5EJxN-a(_8UoP0!{Z2aUDZ-wx8HRv1L-Dv#6Hk6YQ?k%{}_ z>D{dC$59mc>Ekt@UNijD^GAX9-A(H2;VnP`iw z%q+B}Unqv+m^gkVJH6KSczWEad^LX!y^gLExRN=5R7usovZpn*zS`G*sS-W0nYscT z3rV*Va9+l;%yiu_3RBm`xRC^{jm+@)W|9@Rcc=wn%C76Tyd-hmzf*qm?$Sq36FQC8 z39oc^)2%pqDo(f937;l{ZtJV{&MvQD^JzMa2B4_Di@z0z`tSt4Sc=uu5;9A;l8XR+ z{F;gjgqliIPLf%1#W;G1**CB> zA^lZU9LoN-L(y`d=uUss(qrO8m(fWuH5M; z!eGT`a_{pvu4IK;C9J=d75Ov1piz$W2=Nav&{vZ;b9Uq{5Z3y7P6!gn8)9BN7|%uW z!Z;nqBoMg!tvCVZ5I%{s37nymut(Grvo%BD?vx?07zw;6GyIqZSrMiyiKC+gfIuwK zu9paX3qa8fpg%>@c;VX^FP^HE$reOjJ8<31a@}^!x-IHgUH4hnYsnd**PILtCo$z` z36P3r6Sq62YOT=*hDm}EdrKwUsXz=D9qw3M2{mX=4h zRHL`{u6_*D8G5a-7uY*tx@EIq!|S$E+lMJ?c>Xq|9VU|5&%IVRNb2`jYF1WYL8H6L zPvQuCp1?T*B(wYs0Wu_<*vH=`K!!Be0zN?llQfVMRahfISz7iUu7rjZt*DOu^kdkc zlV@anYbE{`9^@oE{A~i{9vrii`#;I}cW6Sql)&&5;sA8mE4YNQF;zno$M-QZ`Xi+7 z;!1uEFk~wEL-K{>2gwJL|9e%2f2_baR^b<`@QGL1Bs=j^Mes1irr{k;_8yyICoxiH zv+NW`EOw2}v3ZPC*!ygOokp+9&agKyH^JUyXVFfwbL>3Y6U=58&`z<7>@Bp@>=Jt$ z?F@T|y^HoFyUc26XW4c3ef9(Fbc$VJb&SlhDj0twtBi@;J{j+Qvfle7U;AV{_6r2a z8|;?|m;{KRHDCre0LBNu_7i|Wu29LMHXtVCe?W-&BX%EtN>*i;1BWwj%r8mBsq_7t4mHR#&iT-~B(P7;*-VUOy;){q1zLf=>T#7JtY3Oe!QW1m>2yGBLK-y3%Nc(TyUtYfF zu0Q-_c_phXefsh8%DTJs@ZPf6hu^}=1F@8*h7{s6TnX)^z!5+pjG}&^7QNXqCXV!A z6oe2j>G}j$@&!N&Pp~0kDWFfG2wWg~xSAkTQw714rXhL-z@q4t0ExJ&TL!d5uL4*V zy@}jUyuAb-rGf2@#VwLpV{r?7#iTR|1okW_T@NI*~#@!HUp2+Jbxg+mcWCachV z?p}q(kt4Z#66PnjH;&%rEn#nt5I37~eR1MpoP@CI4~b6F_)O}SX6cqHf4y^u==|D) zBhO3fLc+O3JN-QXg&Y+45Up@&G6)(N-~?z6T5A;k$v(f`*QyG?ofewKJ%!f5b{jOG z5)bsgK}P0l1TUd7D5PeyocwKH<$r~B1+j0jj}ZK}l3L9QW~;a}zb5`pFyh>VJ4vv4 zVoy<(s7fm~lzw3pS6eGiDGvm*6Cfo8J#HRU?vqH@G-om&&rPpWqD&<2ro9tkl!Pp> z(=8B{1?;|a3L`0e$Xd7=d94Rt#99GQkhK(3MCCy$n6h4*;-|4SUnFpo07-^phRIss zcX`0c6gjgpk-_QcQ2EO_StL&K?UZ;oieN;tvV1?fPH|lv#nCb6Ozi{>X-r(X0tVR& z+Hr(L0>?>fMH#1V1GiW6MqQxIe60Ecyv=AUwSB9CvFPevC%n%CB?0TC57pf zFcEGD)6a{*4`LS_iyXr816-VP5=2Z!iZUkW^csGFz$hXRrZ+3f`1Q{)m51RbtZ#2- zoK14c@#m-QaAKKO93*((bzCAYS?gi6WTSuV`3k}s{yC;)cB=KJ$B!mvkCz|vB}2-l zpeR`bk{HB-f3udx9YM?BIqC*>D~>yLdu=Q3wwT=r>@LE65~H>kM!BZjTgXJym}bR0 zF(27q4#WR1^Wd>=+4SgB8A2S#NWEm+DG@`Xpp_M5 zyktORxKs3eKMmP>@BA{QhbV6#xI^kJ-$_adgZ+{HM+5MYl(9A;`TIlkIpwb+QgAA? zGS78U@(N#MY9lk6NF$MublaUID=)wBgAQ3~p+#A7Bj#-{#p0CbVHkgi{hS#L?0Bia zh5AXF_&n?+a3bB z+l)7{u?Sv8w7?gne2m#URK7GBG?5YyZG_0ePGR7P4dZt)_A6Yu0i&?7H$Scb6h#ev zjZhIRrgjv;`~Wwk2ar=OrFsF1RV2MQna(d09IF>d8*-iM1>+WAlt+r9)|mDmR1kV+ zmJZyJG$SMp_7#AYp*Q*o&cYuPpcp$ZEJ$kDGfQ?fj-_qkjkNXga)lv zMcR{BY9%`l$0M9d@c)4;uY*F452t?6WGbYNUQOJi^igo|PthR`3U^QG1l&FnjaBdq z?jbc0G_Lm5CQ3zn>Odt|C#%wFv00)O0}W%~W7FIN|MpOlSC!p`w2WkMY?ekJE72_6 zQ3dX(uOhIJe1@YDUkC=e2-`|4y_2iN9($a(^riy@wa@)O}y z4?Qu#CdCuh*c1Ocdcu-V^vh|9ow!ZnL8q-Ud>F#W^k`&?&4`hcqmdalAx35~Vqxv6 z+sY<>Z0?mdsJ!?pHPbSiOf3ok*gT!!p7PVJr`n)8nCMsfRkpBQ_(tUq*lA#S=CsnJ zgdXqiPxL34KCkRiAwb;I9md`eW2HCpGs+RbH|G_0mYw_BVCP?n5a=8A*?W(beg$W; zZ!6Evp|2wpDG9fMq@;FXrFTtoKd+|agO*1jq-S3yZ*0dKHCt3vY&hwzpCSvabMRXc z3cvq9)VmI_iA(wS8Gli96y?cXegh--*Z0Y7?Y~EW)Mo!KKz0J(e^NK)NKRc!TK8$K zqs8Gq1sF~x4qfK$x?ADqmSg2Nt#}6+B^Dz`YW%KM_{7xOr*A5}PJmv|Hwat< z*ry6%rar(|r%Gct4O|(5)O5#02|7x{bl0H|1%BWZV~#3PLec(ROO{Q#NvDOc zSsm0~gET>9qZ?5l-?-AOy8Ok`gT<8}FT0;Du5z+1&cp_f+oMDB&&BKUks*k>?SP{s zlNC4>+PFhAMG;{$lwrh2Assx(@L@u}${F)R_JOW+=2y$S;#IwGcmvq*$ASQPtE1B*+#bD%nzU zOh3~=jAfidL^Xw(cl4@eX}w#A+_<#%n!Nbb}Rxq_U^{P%GHM_+yNerBY* z9ngq)g-?bI`3ZfVXn09*>xNTq+`2Iwf_0^;AK9O*Kp%4One8W36kn#GcIZxoCwY!F zoUlDgfv5B^u4DlK6+LY>uQ1I3drK4uidygdci@((A0H}(j^Z`)U@2TQz6%&oTSRSr z{pZ?g7;FY8a=go*3uzjD$`Zt)i0l^N``25|UM+JTP0*YSsDoacpU@n&`o~6J;PD zq=1|#!a0G2MoY4mLZo!2p|OpCyYa?Q`FR)PncCz#G(RC<1R!w)7BZYXca62ALi!G0$|CUz$dyNSq7(FfD>sylEU2tX)DaT&}sfN3_2zJ z3k4KmlP}|r_X!9qJC*LhH{oli(2oe^OP%H@%yK4&bMl`FIH{vk$p>9*=$!GoY25I( zqWW;@s2<6wWXwtAWj(V@y>|h!V%%t=iYU%}97!_sw*0_(hn! 4: + self.on_ticks(self, self._parse_binary(payload)) + + # Parse text messages + if not is_binary: + self._parse_text_message(payload) + + def _on_open(self, ws): + if self.on_open: + return self.on_open(self) + + def _parse_text_message(self, payload): + """Parse text message.""" + # Decode unicode data + if not six.PY2 and type(payload) == bytes: + payload = payload.decode("utf-8") + print("PAYLOAD",payload) + data =base64.b64decode(payload) + print("DATA",data.encode().decode()) + try: + data = json.loads(payload) + print("DATA",data) + except ValueError: + return + + def _parse_binary(self, bin): + print("""Parse binary data to a (list of) ticks structure.""") + packets = self._split_packets(bin) # split data to individual ticks packet + data = [] + + for packet in packets: + instrument_token = self._unpack_int(packet, 0, 4) + segment = instrument_token & 0xff # Retrive segment constant from instrument_token + + divisor = 10000000.0 if segment == self.EXCHANGE_MAP["cds"] else 100.0 + + # All indices are not tradable + tradable = False if segment == self.EXCHANGE_MAP["indices"] else True + try: + last_trade_time = datetime.fromtimestamp(self._unpack_int(packet, 44, 48)) + except Exception: + last_trade_time = None + + try: + timestamp = datetime.fromtimestamp(self._unpack_int(packet, 60, 64)) + except Exception: + timestamp = None + + d["last_trade_time"] = last_trade_time + d["oi"] = self._unpack_int(packet, 48, 52) + d["oi_day_high"] = self._unpack_int(packet, 52, 56) + d["oi_day_low"] = self._unpack_int(packet, 56, 60) + d["timestamp"] = timestamp + + # Market depth entries. + depth = { + "buy": [], + "sell": [] + } + + # Compile the market depth lists. + for i, p in enumerate(range(64, len(packet), 12)): + depth["sell" if i >= 5 else "buy"].append({ + "quantity": self._unpack_int(packet, p, p + 4), + "price": self._unpack_int(packet, p + 4, p + 8) / divisor, + "orders": self._unpack_int(packet, p + 8, p + 10, byte_format="H") + }) + + d["depth"] = depth + + data.append(d) + + return data + + def _unpack_int(self, bin, start, end, byte_format="I"): + """Unpack binary data as unsgined interger.""" + return struct.unpack(">" + byte_format, bin[start:end])[0] + + def _split_packets(self, bin): + """Split the data to individual packets of ticks.""" + # Ignore heartbeat data. + if len(bin) < 2: + return [] + + number_of_packets = self._unpack_int(bin, 0, 2, byte_format="H") + packets = [] + + j = 2 + for i in range(number_of_packets): + packet_length = self._unpack_int(bin, j, j + 2, byte_format="H") + packets.append(bin[j + 2: j + 2 + packet_length]) + j = j + 2 + packet_length + + return packets + + diff --git a/example/sample.py b/example/sample.py index bbf030f..eb9f1fb 100644 --- a/example/sample.py +++ b/example/sample.py @@ -1,17 +1,39 @@ # package import statement -from smartapi import smartConnect as sc +from smartapi.smartConnect import SmartConnect -# creating object of the class SmartConnect -obj = sc.SmartConnect() +obj=SmartConnect() +#login api call +data = obj.generateSession('D88311','Angel@444') +refreshToken= data['data']['refreshToken'] -# function to call the login api +#fetch User Profile +userProfile= obj.getProfile(refreshToken) -def loginApiCall(clientcode, password): - print(clientcode, password) - login_response = obj.generateSession(clientcode, password) - print("Logged in Successfully") - return login_response +#place order +try: + orderparams = { + "variety": "NORMAL", + "tradingsymbol": "SBIN-EQ", + "symboltoken": "3045", + "transactiontype": "BUY", + "exchange": "NSE", + "ordertype": "LIMIT", + "producttype": "INTRADAY", + "duration": "DAY", + "price": "19500", + "squareoff": "0", + "stoploss": "0", + "quantity": "1" + } + orderId=obj.placeOrder(orderparams) + print("The order id is: {}".format(orderId)) +except Exception as e: + print("Order placement failed: {}".format(e.message)) - -print(loginApiCall('D88311', 'Angel@444')) +#logout +try: + logout=obj.terminateSession('D88311') + print("Logout Successfull") +except Exception as e: + print("Logout failed: {}".format(e.message)) \ No newline at end of file diff --git a/test/test.py b/test/test.py index b6de560..1ce0ae0 100644 --- a/test/test.py +++ b/test/test.py @@ -2,56 +2,93 @@ import os dir = os.getcwd() -#print(dir) -# path=dir.split("\") +print(dir) +#paths=dir.split("\") sys.path.append(dir + "\SmartApi") -#print(sys.path) - -import smartapi.smartConnect - -smartApi = smartapi.smartConnect.SmartConnect() - -login = smartApi.generateSession('D88311', 'Angel@444') -refreshToken = login['data']['refreshToken'] -smartApi.getProfile(refreshToken) -smartApi.generateToken(refreshToken) -orderparams = { - "variety": "NORMAL", - "tradingsymbol": "SBIN-EQ", - "symboltoken": "3045", - "transactiontype": "BUY", - "exchange": "NSE", - "ordertype": "LIMIT", - "producttype": "INTRADAY", - "duration": "DAY", - "price": "19500", - "squareoff": "0", - "stoploss": "0", - "quantity": "1" -} -orderid = smartApi.placeOrder(orderparams) - -modifyparams = { - "variety": "NORMAL", - "orderid": orderid, - "ordertype": "LIMIT", - "producttype": "INTRADAY", - "duration": "DAY", - "price": "19500", - "quantity": "1" -} -smartApi.modifyOrder(modifyparams) - -smartApi.cancelOrder(orderid, "NORMAL") - -smartApi.orderBook() -smartApi.tradeBook() -smartApi.rmsLimit() -smartApi.position() -smartApi.holding() -exchange = "NSE" -tradingsymbol = "SBIN-EQ" -symboltoken = 3045 -smartApi.ltpData("NSE", "SBIN-EQ", "3045") -smartApi.terminateSession(login['data']['clientcode']) +print(sys.path) + +# import smartConnect + +# smartApi = smartConnect.SmartConnect() + +# login = smartApi.generateSession('D88311', 'Angel@444') +# print(login) +# refreshToken = login['data']['refreshToken'] +# smartApi.getProfile(refreshToken) +# smartApi.generateToken(refreshToken) +# orderparams = { +# "variety": "NORMAL", +# "tradingsymbol": "SBIN-EQ", +# "symboltoken": "3045", +# "transactiontype": "BUY", +# "exchange": "NSE", +# "ordertype": "LIMIT", +# "producttype": "INTRADAY", +# "duration": "DAY", +# "price": "19500", +# "squareoff": "0", +# "stoploss": "0", +# "quantity": "1" +# } +# orderid = smartApi.placeOrder(orderparams) + +# modifyparams = { +# "variety": "NORMAL", +# "orderid": orderid, +# "ordertype": "LIMIT", +# "producttype": "INTRADAY", +# "duration": "DAY", +# "price": "19500", +# "quantity": "1", +# "tradingsymbol":"SBIN-EQ", +# "symboltoken":"3045", +# "exchange":"NSE" +# } +# smartApi.modifyOrder(modifyparams) + +# smartApi.cancelOrder(orderid, "NORMAL") + +# smartApi.orderBook() +# smartApi.tradeBook() +# smartApi.rmsLimit() +# smartApi.position() +# smartApi.holding() +# exchange = "NSE" +# tradingsymbol = "SBIN-EQ" +# symboltoken = 3045 +# smartApi.ltpData("NSE", "SBIN-EQ", "3045") +# params={ +# "exchange": "NSE", +# "oldproducttype":"DELIVERY", +# "newproducttype": "MARGIN", +# "tradingsymbol": "SBIN-EQ", +# "transactiontype":"BUY", +# "quantity":1, +# "type":"DAY" + +# } + +# smartApi.convertPosition(params) +# smartApi.terminateSession('D88311') + +from socketTP import SmartSocket +FEED_TOKEN='2017967114' +CLIENT_CODE='S212741' +token=None +ss = SmartSocket(FEED_TOKEN, CLIENT_CODE) +def on_tick(ws, tick): + print("Ticks: {}".format(tick)) +def on_connect(ws, response): + ws.send_request(token) + +def on_close(ws, code, reason): + ws.stop() + +# Assign the callbacks. +ss.on_ticks = on_tick +ss.on_connect = on_connect +ss.on_close = on_close + +ss.connect() + From ee48512f6b7e830070094e8dd269f599fa93829f Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Mon, 30 Nov 2020 17:56:23 +0530 Subject: [PATCH 05/49] changes in socket files and readme --- README.md | 24 ++ SmartApi/__pycache__/__init__.cpython-36.pyc | Bin 122 -> 122 bytes .../__pycache__/smartConnect.cpython-36.pyc | Bin 10813 -> 10813 bytes .../__pycache__/smartSocket.cpython-36.pyc | Bin 0 -> 8456 bytes SmartApi/__pycache__/socketTP.cpython-36.pyc | Bin 8986 -> 8916 bytes SmartApi/smartConnect.py | 2 +- SmartApi/smartSocket.py | 359 ++++++++++++++---- SmartApi/socket1.py | 32 -- SmartApi/socketTP.py | 301 --------------- test/test.py | 127 ++++--- 10 files changed, 380 insertions(+), 465 deletions(-) create mode 100644 SmartApi/__pycache__/smartSocket.cpython-36.pyc delete mode 100644 SmartApi/socket1.py delete mode 100644 SmartApi/socketTP.py diff --git a/README.md b/README.md index c2807f8..c8d39ef 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,30 @@ try: except Exception as e: print("Logout failed: {}".format(e.message)) +#websocket +from smartapi.smartSocket import SmartSocket +FEED_TOKEN= "your feed token" +CLIENT_CODE="your client code" +token="channel you want the information of" #"nse_cm|2885&nse_cm|1594&nse_cm|11536" + +ss = SmartSocket(FEED_TOKEN, CLIENT_CODE) + +def on_tick(ws, tick): + print("Ticks: {}".format(tick)) + +def on_connect(ws, response): + ws.send_request(token) + +def on_close(ws, code, reason): + ws.stop() + +# Assign the callbacks. +ss.on_ticks = on_tick +ss.on_connect = on_connect +ss.on_close = on_close + +ss.connect( ) + License MIT diff --git a/SmartApi/__pycache__/__init__.cpython-36.pyc b/SmartApi/__pycache__/__init__.cpython-36.pyc index d9cb64366e71c1538c60371f05df7862bf84ba8a..f619741a91256bb1d9bdccb6de0f3f4660282320 100644 GIT binary patch delta 15 Wcmb=b;xy*v<(lw(bv(yJ&O!hsDFo>N delta 15 Wcmb=b;xy*v<=P-KF`i)}XCVL|-~=21 diff --git a/SmartApi/__pycache__/smartConnect.cpython-36.pyc b/SmartApi/__pycache__/smartConnect.cpython-36.pyc index 3f5e4801c3d97d04318920e21ff166084da359ad..2f026f4f4c0f646094054cef2dd68a0260e5aabf 100644 GIT binary patch delta 18 ZcmdlRvNwd&n3tC;>*0}j`;D9?S^z&(21oz^ delta 18 ZcmdlRvNwd&n3tC;Ie1;X^+rw;EdV+91(^T< diff --git a/SmartApi/__pycache__/smartSocket.cpython-36.pyc b/SmartApi/__pycache__/smartSocket.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..99c5ce76ec693eecd9d0c7dd42322946387804f2 GIT binary patch literal 8456 zcmb_h&2Jn>cJHt0>G|NND3YRWsco;d8fP`ywY6TyVYCt`YNhp>QcOCsI$pGUx|(DU zd%8!}H6l4XV;D;X3oIbRmmC5Z!5;Roxdgcd2yzIJoN~%7K<5%5C;kh2Nq(=oXE>y! zH3DP?{pzEut6#lW@AuxTes^lB`n&)7SNGR%E6RT>6F&p>o4C@y2Vn|RBgM%})lp?z zb2M4%jxI~XF=SbCO0qN^QY`Z2gx zHX3SXF;4^{>;w%hEAznfMZz;ZO(WdXqhzO{XG;%*)@I`G1!64%Zu<0^(N8Zb=_)FLLSk~XUn$!vQJXIj35;IYjSeaQU zO;%x5l;vM3hT>RYzm{Ft?08(fh$~+$UPG^=YX(=k2qF}r4wNIUtqs(H_LWNV#ANCQ z)>uk=-GK87hGmxPhH)rd7yU*WMBAC+@trg?_x7oTU@ETbM_!t`?%yiEe|znN&r;&X z>xNgmhhjI0KaW2A^oXuwUkk>H(Jn^G}C~E(WmoB3@V#1e0F`7zR&l;}u4Uhr; zZNXC-Ek)E~wkJh{>3YfjW8^rclUv?VsCjqw$MTJRh?|Z2oq{3@O zVY(YI5=wcyP^h+_X4NEii{TB8*YW<$;z8O?V$3y*W=`hlMkR^Y@-1*4&C~=@G)uG8 z{+lmf@c5ar21%2&YPsTNROAX(zL1yD<%AA3PJ+$KU^D3kaYL0np5@F;;`_M!Du$+H z!iox}>_5a54fjdz^rMmnZ6(Odi1?g95gFADpCy&sBQn+4lmFA}y75NUb-p4|z6Z_Iw;MZF+x-q~nW zvl0thy&ZlIEbt{FuMxRO8zYxzDHXCJ57|Gux@*N_C?T*zgoL8=R+FCDBEiv1~CC$!K4NbD|qi6i1Mcu@e z{v*gpspQPak&zQ42S(28n+lv;4UVl2r&fnUyT+#3%u^Mff0oU`wOQ=@Y@VG%PlYY8 z^XRFvAFxHXgq|9Ehb^-UsMXmDdj$=VSQ#7u$aa$HK1&_FMa|ZB;+Uw(o{oRult9vhtQ^KH^nrO#Rav@`uP6+E%%d; z?_~y05|LGjSyv=`L7dfm84kfKvVeaVFP2azLVqvK4MEy~v<7JdWDSi{j{em<>+84O zt@|IYZ)CN#pWR#E*mBqI-(HvV@E>C2$+pa)h74i@S4wj!YMl(iF!d9&=r2qtacl?U z@PTwm*N3>$PeBAc!L|&9uzU(4R0KvOETs)WwN(gAX&bUu0ySl=3`)XP-3n+`)@q=2 zS(_^S#9M37kqB&WBI3w}H4$;ZS4`)SK#n`dk6emw;lrgA5p0cIiA0vXEggyknXE?l z3+E~kC+{iTlZ2lFZydeHBZ)U>gqzK~zT|im;UFM#NlrQVOzTyxs#n$g-@kZD&d)tK z_Pk^+v^m#kreA_UMs%rp*fJ#9YHgig9%yxdqcGZ~BV}j^lC(B32uPm6Cx^6hUQE| zKq5F01#miLN&=FexZ|7;W5j_`v>EQiUUb)sSrqUT`GF}A{{})zaH}!HZ(=5Xod{{r zvBGpS@OwPq1R2gko-H5{oOlf<~N&N2&A1h9dN{KZ9l8*YcbC!ox%1l&J3bY_Z0yG3N{ z7)e*8XLm!n*gIXYnXZ5+T3s`=Y1PtZbps}6=$1NSpJ{7>efq9@C zg|8587h(IJ##hK{7(B3q9erc#4)!a#Q@KtNIMvOqTU+by{RivF*yNhea$H9YS-d=8 zzs93Q%)JP|)t`(dnv(-hg|(y;xl>1h_BhO@kd_jPB3aTTZ%!o*VwOi*c|^-EVFqp! zA+yN|`SQ%nerPh1m<+8?5}Ql%-L}{bCP608I-qf&i^}ie z(NV1NQtnC;Oa6+OBR8UG{kcijaZ(y@=VZ!0sVPw!>|^{STgNI_B_zeQ!B4zZqo zV-pFDu=c9_Z&cu=s`M%Kt*{ahu{JPhPG&wsYWPd#q4Eg(mSNNv#-~cGeVXs$@`j`N zaRzVf7{W{UoH9u<4x+4-yLJP5;*RP0z6jY?|I#{TGRUD3huA!LjM!Hog+?e7?|fkY zVhAzXSbL++-$TKFM1&03snMV!Bg3gmc#x^B%xELoLD<~ubknS|e&7dP!YH|0GjluP z9Zz7e;6<>&KccDT(XsCde;4_=NPQl5Q$T3WOQt@Tg4gNIZgKxNm>?y)Mh2y6+9G0y zd3_N;Hm@7%th%V4#)!#BUu=^y^_BSsB(HKxf6;moPE7jW+{e?Az!`+#KStj_;L2f3 z#`^uG$xTN-euS>%UFb*U*uQ=c4FM|zADWh$+mKHh_H(lqOH>i_)r}H=lyPF?5r& zqf5$-k_wU-pCw8sYehJM(@|B%;l-g}uD>%}{0W}^4_vu-hxwk#MPR&iCO3XHsf+R% z`RXUAkQYS^Ov(Xz3ms9>>OgHH20l`Us-SZVsUGP!s82&5DGe$+TozUvCmE-EA1d(z zyhIgVVpoNKhBDzdfdBGrd58oZiEp`o?g8n+o>XA7U+RhNtM5DI2e%&m?EbCWj&b|e z)~$^(_jF)Ey4b{({vDzLDKh!~9c8G0tsZes( zRoq!vRd(=a=fBa0wSzC|jEPN&3i)HUNF3Z&e!lyeHmnb)2DL$*E$x-QR{2e~j8$H^ zP~?&WV=y(CV%m~&By&(|QwwxO_LW~Lc+7i1Us+P~(YSD<2edIbAjO?Y;MLwms zdWZ50Lv&2$%dZmICK3>lucR}kOudVb4z<>y2;4k8Xy}fGL(Eu&;?Ng?e49OpRBtd-Fmon*f9YFRl&SYlot=$CC<^Kb zh;fi?z~m?>*Z)$xfG=hYR2~pt`9$s@JO5r`la_5{FTFV331iA^kn7`!fH!}y-jGH{ zrv{{ZUpQvI`$j=+O3S+qlIe(4d7GMN+)4+1D=^hjUUoVnJlV`+WG>?Yx};zE5*0e* zlFlA;?_dcM-;kRiKY<5$W(+k#Y^Dy4g9mwF0F=57oF*KE7znw6FZoy#IHFT8^%c}y zQly9|(#-qOGc+DwC)9z+O8w?08KF!GrMQsk(HZEIkl`Z)@-%5McCu~DgTp3&8*JzJ z6ru*_OOnCvAfw|X5&oD6r`~dY7(k+Q=3u3*fV;`|$l$p^f2OuMd01yEf0c{yV+YaP z8Bs?Va*;$$fqCm5EI52wI`lTqZ7p;b(*OsY5S^L5Tyil%xE%QaIW>)@6AY;$*eLix2t+UlA_*6e3#2#~A$lQ7#2?^x z);4xZZ0yBK3&F}Ff5Fm5!P%rz7G~!?-p-r1*X!?V)^ai#AC8_5PVcQ1+kOE62_6m* z!J{5^&s5!ZXF~9WZ^(#m%BUX;#efA`A|Vv&#$Iy&QsdXr8W4uliEA3QR#HJ89x`q%EI|$Sq2IWu$Wl13o(8IRDm|52F zlA0S3>%`F}V?$$|qy`0{?lP;QQi!OpOw&y0HApqG5B+2ABu_}dcq#{zqD?#%eMA35 z4`sxoa6DIN(N4eH=UJo5s2LZd?TBvnjXL8=)-I_j#{PSp4BWBy_VW{x2Ds2Y2jdea)yuY6=7d(&wt{% HD(6SPayn-? delta 498 zcmYjNJxc>Y5S`h(+vH*tT!TqKqk@IOMlb{{1PiqhLNK5~5H)TJFBsu+P2dj2v$C*o zu@QfQO^B8F7c2y;6e1R4XJ;okdr^>Kc9@TS@69}~T(8>mgM*3S;eMynu@{B-000jp zhKL|pz}h#eDst*pjH+FcGDB*pOEEViO`rMTAi0iA@*7JxqkpjqnBdusg!`smMH4Mm z9{J8q5;R~OO~&XQCFeM8{Kf8J>XB`4{G-?K?pU9M$c)fH&{XcSZ@9~z;j<7WYnYTr zBIqSiB!SVK(ORe6(m5>x704SUb&+0*<++#fN?ssfEnl@%b;chYr&aIwrv_ z6A^9YnGNQaeRM2IkO9(-bY0JJC#EL?Ml}-P#6uzuLHF7j&vp|3ySlmw%@o~dfbQcX zXd{6Fsvs@N&mb@&y|I!y$j)}JvSpJe` 4: + self.on_ticks(self, self._parse_binary(payload)) + + # Parse text messages + if not is_binary: + self._parse_text_message(payload) + + def _on_open(self, ws): + if self.on_open: + return self.on_open(self) + + def _parse_text_message(self, payload): + """Parse text message.""" + # Decode unicode data + if not six.PY2 and type(payload) == bytes: + payload = payload.decode("utf-8") + print("PAYLOAD",payload) + data =base64.b64decode(payload) + print("DATA",data) + try: + data = json.loads(payload) + print("DATA",data) + except ValueError: + return + + def _parse_binary(self, bin): + #print("""Parse binary data to a (list of) ticks structure.""") + packets = self._split_packets(bin) # split data to individual ticks packet + data = [] + + for packet in packets: + instrument_token = self._unpack_int(packet, 0, 4) + segment = instrument_token & 0xff # Retrive segment constant from instrument_token + + divisor = 10000000.0 if segment == self.EXCHANGE_MAP["cds"] else 100.0 + + # All indices are not tradable + tradable = False if segment == self.EXCHANGE_MAP["indices"] else True + try: + last_trade_time = datetime.fromtimestamp(self._unpack_int(packet, 44, 48)) + except Exception: + last_trade_time = None + + try: + timestamp = datetime.fromtimestamp(self._unpack_int(packet, 60, 64)) + except Exception: + timestamp = None + + d["last_trade_time"] = last_trade_time + d["oi"] = self._unpack_int(packet, 48, 52) + d["oi_day_high"] = self._unpack_int(packet, 52, 56) + d["oi_day_low"] = self._unpack_int(packet, 56, 60) + d["timestamp"] = timestamp + + # Market depth entries. + depth = { + "buy": [], + "sell": [] + } + + # Compile the market depth lists. + for i, p in enumerate(range(64, len(packet), 12)): + depth["sell" if i >= 5 else "buy"].append({ + "quantity": self._unpack_int(packet, p, p + 4), + "price": self._unpack_int(packet, p + 4, p + 8) / divisor, + "orders": self._unpack_int(packet, p + 8, p + 10, byte_format="H") + }) + + d["depth"] = depth + + data.append(d) + + return data + + def _unpack_int(self, bin, start, end, byte_format="I"): + """Unpack binary data as unsgined interger.""" + return struct.unpack(">" + byte_format, bin[start:end])[0] + + def _split_packets(self, bin): + """Split the data to individual packets of ticks.""" + # Ignore heartbeat data. + if len(bin) < 2: + return [] + + number_of_packets = self._unpack_int(bin, 0, 2, byte_format="H") + packets = [] + + j = 2 + for i in range(number_of_packets): + packet_length = self._unpack_int(bin, j, j + 2, byte_format="H") + packets.append(bin[j + 2: j + 2 + packet_length]) + j = j + 2 + packet_length + + return packets + diff --git a/SmartApi/socket1.py b/SmartApi/socket1.py deleted file mode 100644 index e540fdf..0000000 --- a/SmartApi/socket1.py +++ /dev/null @@ -1,32 +0,0 @@ -# import websocket -# import ssl -# import base64 -# ws = websocket.WebSocket() -# from websocket import create_connection -# FEED_TOKEN='125645827' -# CLIENT_CODE='S212741' -# ws= create_connection("wss://omnefeeds.angelbroking.com/NestHtml5Mobile/socket/stream",sslopt={"cert_reqs": ssl.CERT_NONE}) -# _req='{"task":"cn","channel":"","token":"' + FEED_TOKEN + '","user": "' + CLIENT_CODE + '","acctid":"' + CLIENT_CODE + '"}'; -# ws.send(_req) -# strwatchlistscrips = "nse_cm|2885&nse_cm|1594&nse_cm|11536"; -# _req = '{"task":"cn","channel":"'+strwatchlistscrips+'","token":"' + FEED_TOKEN + '","user": "' + CLIENT_CODE + '","acctid":"' + CLIENT_CODE + '"}'; -# ws.send(_req) -# print("Sent") -# print("Receiving...") -# result = ws.recv() -# print(result) -# #str = unicode(str, errors='ignore') -# print("Received '%s'" % result.decode(encoding="utf-8")) -# ws.close() - -import asyncio -import websockets - -async def message(): - async with websockets.connect("wss://omnefeeds.angelbroking.com/NestHtml5Mobile/socket/stream") as socket: - await socket.send({"task":"cn","channel":"","token":"' + FEED_TOKEN + '","user": "' + CLIENT_CODE + '","acctid":"' + CLIENT_CODE + '"}) - strwatchlistscrips = "nse_cm|2885&nse_cm|1594&nse_cm|11536" - await socket.send({"task":"cn","channel":strwatchlistscrips,"token":"' + FEED_TOKEN + '","user": "' + CLIENT_CODE + '","acctid":"' + CLIENT_CODE + '"}) - print(await socket.recv()) - -asyncio.get_event_loop().run_until_complete(message()) diff --git a/SmartApi/socketTP.py b/SmartApi/socketTP.py deleted file mode 100644 index 8149ab3..0000000 --- a/SmartApi/socketTP.py +++ /dev/null @@ -1,301 +0,0 @@ -import six -import sys -import time -import json -import struct -import logging -import threading -import base64 -from datetime import datetime -from twisted.internet import reactor, ssl -from twisted.python import log as twisted_log -from autobahn.twisted.websocket import WebSocketClientProtocol, \ - WebSocketClientFactory, connectWS - - -class SmartSocketClientProtocol(WebSocketClientProtocol): - def __init__(self, *args, **kwargs): - super(SmartSocketClientProtocol,self).__init__(*args,**kwargs) - - def onConnect(self, response): # noqa - """Called when WebSocket server connection was established""" - self.factory.ws = self - - if self.factory.on_connect: - self.factory.on_connect(self, response) - - def onOpen(self): - if self.factory.on_open: - self.factory.on_open(self) - - def onMessage(self, payload, is_binary): # noqa - print("""Called when text or binary message is received.""",payload,is_binary) - if self.factory.on_message: - self.factory.on_message(self, payload, is_binary) - - def onClose(self, was_clean, code, reason): # noqa - """Called when connection is closed.""" - if not was_clean: - if self.factory.on_error: - self.factory.on_error(self, code, reason) - - if self.factory.on_close: - self.factory.on_close(self, code, reason) - -class SmartSocketClientFactory(WebSocketClientFactory): - protocol = SmartSocketClientProtocol - - def __init__(self, *args, **kwargs): - """Initialize with default callback method values.""" - self.debug = False - self.ws = None - self.on_open = None - self.on_error = None - self.on_close = None - self.on_message = None - self.on_connect = None - - - super(SmartSocketClientFactory, self).__init__(*args, **kwargs) - - -class SmartSocket(object): - EXCHANGE_MAP = { - "nse": 1, - "nfo": 2, - "cds": 3, - "bse": 4, - "bfo": 5, - "bsecds": 6, - "mcx": 7, - "mcxsx": 8, - "indices": 9 - } - ROOT_URI='wss://omnefeeds.angelbroking.com/NestHtml5Mobile/socket/stream' - feed_token=None - client_code=None - def __init__(self, FEED_TOKEN, CLIENT_CODE, debug=False, root=None): - self.root = root or self.ROOT_URI - self.feed_token= FEED_TOKEN - self.client_code= CLIENT_CODE - - - # Debug enables logs - self.debug = debug - - # Placeholders for callbacks. - self.on_ticks = None - self.on_open = None - self.on_close = None - self.on_error = None - self.on_connect = None - self.on_message = None - - def _create_connection(self, url, **kwargs): - """Create a WebSocket client connection.""" - self.factory = SmartSocketClientFactory(url, **kwargs) - - # Alias for current websocket connection - self.ws = self.factory.ws - - self.factory.debug = self.debug - - # Register private callbacks - self.factory.on_open = self._on_open - self.factory.on_error = self._on_error - self.factory.on_close = self._on_close - self.factory.on_message = self._on_message - self.factory.on_connect = self._on_connect - - - def connect(self, threaded=False, disable_ssl_verification=False, proxy=None): - print("Connect") - self._create_connection(self.ROOT_URI) - - context_factory = None - print(self.factory.isSecure,disable_ssl_verification) - if self.factory.isSecure and not disable_ssl_verification: - context_factory = ssl.ClientContextFactory() - print("context_factory",context_factory) - connectWS(self.factory, contextFactory=context_factory, timeout=30) - - # Run in seperate thread of blocking - opts = {} - - # Run when reactor is not running - if not reactor.running: - if threaded: - print("inside threaded") - # Signals are not allowed in non main thread by twisted so suppress it. - opts["installSignalHandlers"] = False - self.websocket_thread = threading.Thread(target=reactor.run, kwargs=opts) - self.websocket_thread.daemon = True - self.websocket_thread.start() - else: - reactor.run(**opts) - - def is_connected(self): - print("Check if WebSocket connection is established.") - if self.ws and self.ws.state == self.ws.STATE_OPEN: - return True - else: - return False - def _close(self, code=None, reason=None): - print("Close the WebSocket connection.") - if self.ws: - self.ws.sendClose(code, reason) - - def close(self, code=None, reason=None): - """Close the WebSocket connection.""" - self._close(code, reason) - - def stop(self): - """Stop the event loop. Should be used if main thread has to be closed in `on_close` method. - Reconnection mechanism cannot happen past this method - """ - print("stop") - reactor.stop() - - def send_request(self,token): - print('Request Send') - strwatchlistscrips = "nse_cm|2885&nse_cm|1594&nse_cm|11536" #or token - #token_scripts=token //dynamic call - try: - print("Inside") - request={"task":"cn","channel":"","token":self.feed_token,"user":self.client_code,"acctid":self.client_code} - self.ws.sendMessage( - six.b(json.dumps(request)) - ) - - request={"task":"cn","channel":strwatchlistscrips,"token":self.feed_token,"user":self.client_code,"acctid":self.client_code} - #request={"task":"cn","channel":token_scripts,"token":self.feed_token,"user":self.client_code,"acctid":self.client_code} //dynamic call - self.ws.sendMessage( - six.b(json.dumps(request)) - ) - - return True - except Exception as e: - self._close(reason="Error while request sending: {}".format(str(e))) - raise - - def _on_connect(self, ws, response): - self.ws = ws - if self.on_connect: - self.on_connect(self, response) - - def _on_close(self, ws, code, reason): - """Call `on_close` callback when connection is closed.""" - print("Connection closed: {} - {}".format(code, str(reason))) - - if self.on_close: - self.on_close(self, code, reason) - - def _on_error(self, ws, code, reason): - """Call `on_error` callback when connection throws an error.""" - print("Connection error: {} - {}".format(code, str(reason))) - - if self.on_error: - self.on_error(self, code, reason) - - def _on_message(self, ws, payload, is_binary): - """Call `on_message` callback when text message is received.""" - if self.on_message: - self.on_message(self, payload, is_binary) - - # If the message is binary, parse it and send it to the callback. - if self.on_ticks and is_binary and len(payload) > 4: - self.on_ticks(self, self._parse_binary(payload)) - - # Parse text messages - if not is_binary: - self._parse_text_message(payload) - - def _on_open(self, ws): - if self.on_open: - return self.on_open(self) - - def _parse_text_message(self, payload): - """Parse text message.""" - # Decode unicode data - if not six.PY2 and type(payload) == bytes: - payload = payload.decode("utf-8") - print("PAYLOAD",payload) - data =base64.b64decode(payload) - print("DATA",data.encode().decode()) - try: - data = json.loads(payload) - print("DATA",data) - except ValueError: - return - - def _parse_binary(self, bin): - print("""Parse binary data to a (list of) ticks structure.""") - packets = self._split_packets(bin) # split data to individual ticks packet - data = [] - - for packet in packets: - instrument_token = self._unpack_int(packet, 0, 4) - segment = instrument_token & 0xff # Retrive segment constant from instrument_token - - divisor = 10000000.0 if segment == self.EXCHANGE_MAP["cds"] else 100.0 - - # All indices are not tradable - tradable = False if segment == self.EXCHANGE_MAP["indices"] else True - try: - last_trade_time = datetime.fromtimestamp(self._unpack_int(packet, 44, 48)) - except Exception: - last_trade_time = None - - try: - timestamp = datetime.fromtimestamp(self._unpack_int(packet, 60, 64)) - except Exception: - timestamp = None - - d["last_trade_time"] = last_trade_time - d["oi"] = self._unpack_int(packet, 48, 52) - d["oi_day_high"] = self._unpack_int(packet, 52, 56) - d["oi_day_low"] = self._unpack_int(packet, 56, 60) - d["timestamp"] = timestamp - - # Market depth entries. - depth = { - "buy": [], - "sell": [] - } - - # Compile the market depth lists. - for i, p in enumerate(range(64, len(packet), 12)): - depth["sell" if i >= 5 else "buy"].append({ - "quantity": self._unpack_int(packet, p, p + 4), - "price": self._unpack_int(packet, p + 4, p + 8) / divisor, - "orders": self._unpack_int(packet, p + 8, p + 10, byte_format="H") - }) - - d["depth"] = depth - - data.append(d) - - return data - - def _unpack_int(self, bin, start, end, byte_format="I"): - """Unpack binary data as unsgined interger.""" - return struct.unpack(">" + byte_format, bin[start:end])[0] - - def _split_packets(self, bin): - """Split the data to individual packets of ticks.""" - # Ignore heartbeat data. - if len(bin) < 2: - return [] - - number_of_packets = self._unpack_int(bin, 0, 2, byte_format="H") - packets = [] - - j = 2 - for i in range(number_of_packets): - packet_length = self._unpack_int(bin, j, j + 2, byte_format="H") - packets.append(bin[j + 2: j + 2 + packet_length]) - j = j + 2 + packet_length - - return packets - - diff --git a/test/test.py b/test/test.py index 1ce0ae0..1d67ec7 100644 --- a/test/test.py +++ b/test/test.py @@ -2,86 +2,86 @@ import os dir = os.getcwd() -print(dir) +#print(dir) #paths=dir.split("\") sys.path.append(dir + "\SmartApi") -print(sys.path) +#print(sys.path) -# import smartConnect +import smartConnect -# smartApi = smartConnect.SmartConnect() +smartApi = smartConnect.SmartConnect() -# login = smartApi.generateSession('D88311', 'Angel@444') -# print(login) -# refreshToken = login['data']['refreshToken'] -# smartApi.getProfile(refreshToken) -# smartApi.generateToken(refreshToken) -# orderparams = { -# "variety": "NORMAL", -# "tradingsymbol": "SBIN-EQ", -# "symboltoken": "3045", -# "transactiontype": "BUY", -# "exchange": "NSE", -# "ordertype": "LIMIT", -# "producttype": "INTRADAY", -# "duration": "DAY", -# "price": "19500", -# "squareoff": "0", -# "stoploss": "0", -# "quantity": "1" -# } -# orderid = smartApi.placeOrder(orderparams) +login = smartApi.generateSession('D88311', 'Angel@444') +print(login) +refreshToken = login['data']['refreshToken'] +smartApi.getProfile(refreshToken) +smartApi.generateToken(refreshToken) +orderparams = { + "variety": "NORMAL", + "tradingsymbol": "SBIN-EQ", + "symboltoken": "3045", + "transactiontype": "BUY", + "exchange": "NSE", + "ordertype": "LIMIT", + "producttype": "INTRADAY", + "duration": "DAY", + "price": "19500", + "squareoff": "0", + "stoploss": "0", + "quantity": "1" +} +orderid = smartApi.placeOrder(orderparams) -# modifyparams = { -# "variety": "NORMAL", -# "orderid": orderid, -# "ordertype": "LIMIT", -# "producttype": "INTRADAY", -# "duration": "DAY", -# "price": "19500", -# "quantity": "1", -# "tradingsymbol":"SBIN-EQ", -# "symboltoken":"3045", -# "exchange":"NSE" -# } -# smartApi.modifyOrder(modifyparams) +modifyparams = { + "variety": "NORMAL", + "orderid": orderid, + "ordertype": "LIMIT", + "producttype": "INTRADAY", + "duration": "DAY", + "price": "19500", + "quantity": "1", + "tradingsymbol":"SBIN-EQ", + "symboltoken":"3045", + "exchange":"NSE" +} +smartApi.modifyOrder(modifyparams) -# smartApi.cancelOrder(orderid, "NORMAL") +smartApi.cancelOrder(orderid, "NORMAL") -# smartApi.orderBook() -# smartApi.tradeBook() -# smartApi.rmsLimit() -# smartApi.position() -# smartApi.holding() -# exchange = "NSE" -# tradingsymbol = "SBIN-EQ" -# symboltoken = 3045 -# smartApi.ltpData("NSE", "SBIN-EQ", "3045") -# params={ -# "exchange": "NSE", -# "oldproducttype":"DELIVERY", -# "newproducttype": "MARGIN", -# "tradingsymbol": "SBIN-EQ", -# "transactiontype":"BUY", -# "quantity":1, -# "type":"DAY" +smartApi.orderBook() +smartApi.tradeBook() +smartApi.rmsLimit() +smartApi.position() +smartApi.holding() +exchange = "NSE" +tradingsymbol = "SBIN-EQ" +symboltoken = 3045 +smartApi.ltpData("NSE", "SBIN-EQ", "3045") +params={ + "exchange": "NSE", + "oldproducttype":"DELIVERY", + "newproducttype": "MARGIN", + "tradingsymbol": "SBIN-EQ", + "transactiontype":"BUY", + "quantity":1, + "type":"DAY" -# } +} -# smartApi.convertPosition(params) -# smartApi.terminateSession('D88311') +smartApi.convertPosition(params) +smartApi.terminateSession('D88311') -from socketTP import SmartSocket -FEED_TOKEN='2017967114' +from smartSocket import SmartSocket +FEED_TOKEN='1731759952' CLIENT_CODE='S212741' token=None ss = SmartSocket(FEED_TOKEN, CLIENT_CODE) def on_tick(ws, tick): print("Ticks: {}".format(tick)) def on_connect(ws, response): - ws.send_request(token) - + a=ws.send_request(token) + print("Back to Function",a) def on_close(ws, code, reason): ws.stop() @@ -90,5 +90,6 @@ def on_close(ws, code, reason): ss.on_connect = on_connect ss.on_close = on_close -ss.connect() +ss.connect( ) + From 161544455340b13b5ac11119671641e8d33ab80f Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Mon, 30 Nov 2020 18:04:01 +0530 Subject: [PATCH 06/49] changes in endpoint url for prod --- .../__pycache__/smartConnect.cpython-36.pyc | Bin 10813 -> 10823 bytes SmartApi/smartConnect.py | 3 ++- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/SmartApi/__pycache__/smartConnect.cpython-36.pyc b/SmartApi/__pycache__/smartConnect.cpython-36.pyc index 2f026f4f4c0f646094054cef2dd68a0260e5aabf..87d7f6cf32a2cff265de5513bc7f0d91c811bc0f 100644 GIT binary patch delta 40 wcmdlRay*37n3tEU;^~oi&yAdM%#4PUGnkdQ3QCi5GK(`(i*z@4F>h7_02@{f;Q#;t delta 29 lcmX>evNwd&n3tC;>*0}j`;DA&%#7-jGnkb&PhsAy1^}2H3BUjV diff --git a/SmartApi/smartConnect.py b/SmartApi/smartConnect.py index 8ff2a2a..0d4b880 100644 --- a/SmartApi/smartConnect.py +++ b/SmartApi/smartConnect.py @@ -21,8 +21,9 @@ class SmartConnect(object): _rootUrl = "https://openapisuat.angelbroking.com" - _loginUrl = "https://openapisuat.angelbroking.com/rest/auth/angelbroking/user/v1/loginByPassword" + #_rootUrl="https://apiconnect.angelbroking.com" _login_url ="https://smartapi.angelbroking.com/login" + #_login_url="https://smartapi.angelbroking.com/publisher-login" _default_timeout = 7 # In seconds # Products PRODUCT_MIS = "MIS" From 29a05e26d8756463d87704091341771a3524a133 Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Mon, 30 Nov 2020 18:07:30 +0530 Subject: [PATCH 07/49] changes in endpoint url for prod --- SmartApi/smartConnect.py | 358 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 358 insertions(+) create mode 100644 SmartApi/smartConnect.py diff --git a/SmartApi/smartConnect.py b/SmartApi/smartConnect.py new file mode 100644 index 0000000..5ea37e6 --- /dev/null +++ b/SmartApi/smartConnect.py @@ -0,0 +1,358 @@ +from six.moves.urllib.parse import urljoin +import sys + +sys.path.append('c:\AngelSmartApi\SmartApi') +import csv +import json +import dateutil.parser +import hashlib +import logging +import datetime +import smartapi.smartExceptions as ex +import requests +from requests import get +import re, uuid +import socket + +from smartapi.version import __version__, __title__ + +log = logging.getLogger(__name__) + + +class SmartConnect(object): + #_rootUrl = "https://openapisuat.angelbroking.com" + _rootUrl="https://apiconnect.angelbroking.com" #prod endpoint + #_login_url ="https://smartapi.angelbroking.com/login" + _login_url="https://smartapi.angelbroking.com/publisher-login" #prod endpoint + _default_timeout = 7 # In seconds + # Products + PRODUCT_MIS = "MIS" + + PRODUCT_CNC = "CNC" + PRODUCT_NRML = "NRML" + PRODUCT_CO = "CO" + PRODUCT_BO = "BO" + + # Order types + ORDER_TYPE_MARKET = "MARKET" + ORDER_TYPE_LIMIT = "LIMIT" + ORDER_TYPE_SLM = "SL-M" + ORDER_TYPE_SL = "SL" + + # Varities + VARIETY_REGULAR = "regular" + VARIETY_BO = "bo" + VARIETY_CO = "co" + VARIETY_AMO = "amo" + + # Transaction type + TRANSACTION_TYPE_BUY = "BUY" + TRANSACTION_TYPE_SELL = "SELL" + + # Validity + VALIDITY_DAY = "DAY" + VALIDITY_IOC = "IOC" + + # Exchanges + EXCHANGE_NSE = "NSE" + EXCHANGE_BSE = "BSE" + EXCHANGE_NFO = "NFO" + EXCHANGE_CDS = "CDS" + EXCHANGE_BFO = "BFO" + EXCHANGE_MCX = "MCX" + EXCHANGE_NCDEX="NCDEX" + + # Status constants + STATUS_COMPLETE = "COMPLETE" + STATUS_REJECTED = "REJECTED" + STATUS_CANCELLED = "CANCELLED" + + _routes = { + "api.login":"/rest/auth/angelbroking/user/v1/loginByPassword", + "api.logout":"/rest/secure/angelbroking/user/v1/logout", + "api.token": "/rest/auth/angelbroking/jwt/v1/generateTokens", + "api.refresh": "/rest/auth/angelbroking/jwt/v1/generateTokens", + "api.user.profile": "/rest/secure/angelbroking/user/v1/getProfile", + + "api.order.place": "/rest/secure/angelbroking/order/v1/placeOrder", + "api.order.modify": "/rest/secure/angelbroking/order/v1/modifyOrder", + "api.order.cancel": "/rest/secure/angelbroking/order/v1/cancelOrder", + "api.order.book":"/rest/secure/angelbroking/order/v1/getOrderBook", + + "api.ltp.data": "/rest/secure/angelbroking/order/v1/getLtpData", + "api.trade.book": "/rest/secure/angelbroking/order/v1/getTradeBook", + "api.rms.limit": "/rest/secure/angelbroking/user/v1/getRMS", + "api.holding": "/rest/secure/angelbroking/portfolio/v1/getHolding", + "api.position": "/rest/secure/angelbroking/order/v1/getPosition", + "api.convert.position": "/rest/secure/angelbroking/order/v1/convertPosition" + } + + def __init__(self, api_key=None, access_token=None, refresh_token=None, userId=None, root=None, debug=False, timeout=None, proxies=None, pool=None, disable_ssl=False): + self.debug = debug + self.api_key = api_key + self.session_expiry_hook = None + self.disable_ssl = disable_ssl + self.access_token = access_token + self.refresh_token = refresh_token + self.userId = userId + self.proxies = proxies if proxies else {} + self.root = root or self._loginUrl + self.timeout = timeout or self._default_timeout + + if pool: + self.reqsession = requests.Session() + reqadapter = requests.adapters.HTTPAdapter(**pool) + self.reqsession.mount("https://", reqadapter) + print("in pool") + else: + self.reqsession = requests + + # disable requests SSL warning + requests.packages.urllib3.disable_warnings() + + def setSessionExpiryHook(self, method): + if not callable(method): + raise TypeError("Invalid input type. Only functions are accepted.") + self.session_expiry_hook = method + + def getUserId(): + return userId; + + def setUserId(self,id): + self.userId=id + + def setAccessToken(self, access_token): + + self.access_token = access_token + + def setRefreshToken(self, refresh_token): + + self.refresh_token = refresh_token + + def login_url(self): + """Get the remote login url to which a user should be redirected to initiate the login flow.""" + return "%s?api_key=%s" % (self._login_url, self.api_key) + + def _request(self, route, method, parameters=None): + """Make an HTTP request.""" + params = parameters.copy() if parameters else {} + + uri =self._routes[route].format(**params) + print(uri) + url = urljoin(self.root, uri) + print(url) + hostname = socket.gethostname() + clientLocalIP=socket.gethostbyname(hostname) + clientPublicIP=get('https://api.ipify.org').text + macAddress = ':'.join(re.findall('..', '%012x' % uuid.getnode())) + privateKey = "test" + accept = "application/json" + userType = "USER" + sourceID = "WEB" + + # Custom headers + headers = { + #"X-SmartApi-Version": "", + #"User-Agent": self._user_agent() + "Content-type":accept, + "X-ClientLocalIP": clientLocalIP, + "X-ClientPublicIP": clientPublicIP, + "X-MACAddress": macAddress, + "Accept": accept, + "X-PrivateKey": privateKey, + "X-UserType": userType, + "X-SourceID": sourceID + } + + #if self.api_key and self.access_token: + if self.access_token: + # set authorization header + + auth_header = self.access_token + headers["Authorization"] = "Bearer {}".format(auth_header) + + if self.debug: + log.debug("Request: {method} {url} {params} {headers}".format(method=method, url=url, params=params, headers=headers)) + + try: + r = requests.request(method, + url, + data=json.dumps(params) if method in ["POST", "PUT"] else None, + params=json.dumps(params) if method in ["GET", "DELETE"] else None, + headers=headers, + verify=not self.disable_ssl, + allow_redirects=True, + timeout=self.timeout, + proxies=self.proxies) + print("The Response Content",r.content) + except Exception as e: + raise e + + if self.debug: + log.debug("Response: {code} {content}".format(code=r.status_code, content=r.content)) + + # Validate the content type. + if "json" in headers["Content-type"]: + try: + data = json.loads(r.content.decode("utf8")) + + except ValueError: + raise ex.DataException("Couldn't parse the JSON response received from the server: {content}".format( + content=r.content)) + + # api error + if data.get("error_type"): + # Call session hook if its registered and TokenException is raised + if self.session_expiry_hook and r.status_code == 403 and data["error_type"] == "TokenException": + self.session_expiry_hook() + + # native errors + exp = getattr(ex, data["error_type"], ex.GeneralException) + raise exp(data["message"], code=r.status_code) + + return data + elif "csv" in headers["Content-type"]: + return r.content + else: + raise ex.DataException("Unknown Content-type ({content_type}) with response: ({content})".format( + content_type=headers["Content-type"], + content=r.content)) + + def _deleteRequest(self, route, params=None): + """Alias for sending a DELETE request.""" + return self._request(route, "DELETE", params) + def _putRequest(self, route, params=None): + """Alias for sending a PUT request.""" + return self._request(route, "PUT", params) + def _postRequest(self, route, params=None): + """Alias for sending a POST request.""" + return self._request(route, "POST", params) + def _getRequest(self, route, params=None): + """Alias for sending a GET request.""" + return self._request(route, "GET", params) + + def generateSession(self,clientCode,password): + + params={"clientcode":clientCode,"password":password} + loginResultObject=self._postRequest("api.login",params) + jwtToken=loginResultObject['data']['jwtToken'] + self.setAccessToken(jwtToken) + refreshToken=loginResultObject['data']['refreshToken'] + self.setRefreshToken(refreshToken) + user=self.getProfile(refreshToken) + + id=user['data']['clientcode'] + #id='D88311' + print(id) + + self.setUserId(id) + user['data']['jwtToken']="Bearer "+jwtToken + user['data']['refreshToken']=refreshToken + print("USER",user) + return user + + def terminateSession(self,clientCode): + logoutResponseObject=self._postRequest("api.logout",{"clientcode":clientCode}) + return logoutResponseObject + + def generateToken(self,refresh_token): + response=self._postRequest('api.token',{"refreshToken":refresh_token}) + jwtToken=response['data']['jwtToken'] + self.setAccessToken(jwtToken) + return response + + def renewAccessToken(self): + + # h = hashlib.sha256(self.api_key.encode("utf-8") + refresh_token.encode("utf-8") + access_token.encode("utf-8")) + # checksum = h.hexdigest() + + response =self._postRequest('api.refresh', { + "jwtToken": self.access_token, + "refreshToken": self.refresh_token, + #"checksum": checksum + }) + + tokenSet={} + + if "jwtToken" in response: + tokenSet['jwtToken']=response['data']['jwtToken'] + tokenSet['clientcode']=self. userId + tokenSet['refreshToken']=response['data']["refreshToken"] + + return tokenSet + + def getProfile(self,refreshToken): + user=self._getRequest("api.user.profile",{"refreshToken":refreshToken}) + print("USER PROFILE",user) + return user + + def placeOrder(self,orderparams): + #params = {"exchange":orderparams.exchange,"symbolToken":orderparams.symboltoken,"transactionType":orderparams.transactionType,"quantity":orderparams.quantity,"price":orderparams.price,"productType":orderparams.producttype,"orderType":orderparams.ordertype,"duration":orderparams.duration,"variety":orderparams.variety,"tradingSymbol":orderparams.tradingsymbol,"triggerPrice":orderparams.trigger_price,"squareoff":orderparams.squareoff,"stoploss":orderparams.stoploss,"trailingStoploss":orderparams.trailing_stoploss,"tag":orderparams.tag} + params=orderparams + + for k in list(params.keys()): + if params[k] is None : + del(params[k]) + + orderResponse= self._postRequest("api.order.place", params)['data']['orderid'] + + return orderResponse + + def modifyOrder(self,orderparams): + params = orderparams + + for k in list(params.keys()): + if params[k] is None: + del(params[k]) + + orderResponse= self._postRequest("api.order.modify", params) + #order=Order(orderResponse) + #order['orderId']=orderResponse['data']['orderid'] + return orderResponse + + def cancelOrder(self, order_id,variety): + orderResponse= self._postRequest("api.order.cancel", {"variety": variety,"orderid": order_id}) + return orderResponse + + def ltpData(self,exchange,tradingsymbol,symboltoken): + params={ + "exchange":exchange, + "tradingsymbol":tradingsymbol, + "symboltoken":symboltoken + } + ltpDataResponse= self._postRequest("api.ltp.data",params) + return ltpDataResponse + + def orderBook(self): + orderBookResponse=self._getRequest("api.order.book") + return orderBookResponse + + + def tradeBook(self): + tradeBookResponse=self._getRequest("api.trade.book") + return tradeBookResponse + + def rmsLimit(self): + rmsLimitResponse= self._getRequest("api.rms.limit") + return rmsLimitResponse + + def position(self): + positionResponse= self._getRequest("api.position") + return positionResponse + + def holding(self): + holdingResponse= self._getRequest("api.holding") + return holdingResponse + + def convertPosition(self,positionParams): + params=positionParams + for k in list(params.keys()): + if params[k] is None: + del(params[k]) + convertPositionResponse= self._postRequest("api.convert.position",params) + + return convertPositionResponse + + def _user_agent(self): + return (__title__ + "-python/").capitalize() + __version__ + From 245cfb81cb183b5f072f6691154f4ebba723a828 Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Mon, 30 Nov 2020 19:05:26 +0530 Subject: [PATCH 08/49] changes in __init__.py --- SmartApi/__init__.py | 7 +++++++ test/test.py | 7 ++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/SmartApi/__init__.py b/SmartApi/__init__.py index fd40910..f5955af 100644 --- a/SmartApi/__init__.py +++ b/SmartApi/__init__.py @@ -1,3 +1,10 @@ +from __future__ import unicode_literals,absolute_import + +from smartapi import smartExceptions +from smartapi.smartConnect import SmartConnect +from smartapi.smartSocket import SmartSocket + +__all__ = ["smartExceptions","SmartConnect","SmartSocket"] diff --git a/test/test.py b/test/test.py index 1d67ec7..c09ab2d 100644 --- a/test/test.py +++ b/test/test.py @@ -8,9 +8,10 @@ sys.path.append(dir + "\SmartApi") #print(sys.path) -import smartConnect +from smartapi import SmartConnect -smartApi = smartConnect.SmartConnect() +smartApi = +SmartConnect() login = smartApi.generateSession('D88311', 'Angel@444') print(login) @@ -72,7 +73,7 @@ smartApi.convertPosition(params) smartApi.terminateSession('D88311') -from smartSocket import SmartSocket +from smartapi import SmartSocket FEED_TOKEN='1731759952' CLIENT_CODE='S212741' token=None From 3689fc66c4c7489942aa1cb2d078ceb1edc5ab78 Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Mon, 30 Nov 2020 19:19:58 +0530 Subject: [PATCH 09/49] changes in sample.py- import statement --- README.md | 4 ++-- example/sample.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c8d39ef..c008a48 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ pip install smartapi-python ```python # package import statement -from smartapi.smartConnect import SmartConnect +from smartapi import SmartConnect #create object of call obj=SmartConnect() @@ -55,7 +55,7 @@ except Exception as e: print("Logout failed: {}".format(e.message)) #websocket -from smartapi.smartSocket import SmartSocket +from smartapi import SmartSocket FEED_TOKEN= "your feed token" CLIENT_CODE="your client code" token="channel you want the information of" #"nse_cm|2885&nse_cm|1594&nse_cm|11536" diff --git a/example/sample.py b/example/sample.py index eb9f1fb..1d5c4f3 100644 --- a/example/sample.py +++ b/example/sample.py @@ -1,5 +1,5 @@ # package import statement -from smartapi.smartConnect import SmartConnect +from smartapi import SmartConnect obj=SmartConnect() #login api call From 87bf4b690c3507aabf52ae26a853854677daef1a Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Mon, 30 Nov 2020 19:23:26 +0530 Subject: [PATCH 10/49] changes in version --- SmartApi/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SmartApi/version.py b/SmartApi/version.py index 6549f56..55bbe6a 100644 --- a/SmartApi/version.py +++ b/SmartApi/version.py @@ -2,7 +2,7 @@ __description__ = "Angel Broking openApi integration" __url__ = "https://www.angelbroking.com/" __download_url__ = "https://github.com/angelbroking-github/smartapi-python" -__version__ = "1.0.1" +__version__ = "1.0.2" __author__ = "ab-smartapi" __token__ = "ab-smartapi" __author_email__ = "smartapi.sdk@gmail.com" From 8c6b181691bea1183bee8a194f4fccae842680b3 Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Mon, 30 Nov 2020 19:30:17 +0530 Subject: [PATCH 11/49] changes in version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 75ec875..03f07aa 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ setup( name="smartapi-python", - version="1.0.1", + version="1.0.2", author="ab-smartapi", author_email="smartapi.sdk@gmail.com", description="Angel Broking openApi integration", From fbdf51fc154f4d1c262e8d7c06e2682032448739 Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Mon, 30 Nov 2020 20:05:27 +0530 Subject: [PATCH 12/49] bugs resolved --- README.md | 4 ++-- .../smartExceptions.cpython-36.pyc | Bin 3677 -> 3677 bytes SmartApi/__pycache__/version.cpython-36.pyc | Bin 480 -> 480 bytes SmartApi/smartConnect.py | 6 +++--- SmartApi/version.py | 2 +- example/sample.py | 2 +- setup.py | 2 +- test/test.py | 9 ++++----- 8 files changed, 12 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index c008a48..c8d39ef 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ pip install smartapi-python ```python # package import statement -from smartapi import SmartConnect +from smartapi.smartConnect import SmartConnect #create object of call obj=SmartConnect() @@ -55,7 +55,7 @@ except Exception as e: print("Logout failed: {}".format(e.message)) #websocket -from smartapi import SmartSocket +from smartapi.smartSocket import SmartSocket FEED_TOKEN= "your feed token" CLIENT_CODE="your client code" token="channel you want the information of" #"nse_cm|2885&nse_cm|1594&nse_cm|11536" diff --git a/SmartApi/__pycache__/smartExceptions.cpython-36.pyc b/SmartApi/__pycache__/smartExceptions.cpython-36.pyc index 8f9b5aa985bb0e1a1e0bb9b191002e1c45efda26..0abc8e087c8daca464e62acd1f3d0e6a089aeb77 100644 GIT binary patch delta 16 XcmcaBb61Aln3tF9-n%0k*~9n%Gv5XM delta 16 XcmcaBb61Aln3tDpDeKCO>|uNWEK>x) diff --git a/SmartApi/__pycache__/version.cpython-36.pyc b/SmartApi/__pycache__/version.cpython-36.pyc index 289b8a749518b7cceada335149ee19d1674de2b2..5c18fcb3a55deda9eb0f6d3343285d535f761f4c 100644 GIT binary patch delta 20 ccmaFB{D7I=n3tDp&d(zg*>5o#O?>nZ08MQOlmGw# delta 20 ccmaFB{D7I=n3tDpE7Qt}?6(*VCqDWI07K&kng9R* diff --git a/SmartApi/smartConnect.py b/SmartApi/smartConnect.py index 0d4b880..1bda6e1 100644 --- a/SmartApi/smartConnect.py +++ b/SmartApi/smartConnect.py @@ -1,7 +1,6 @@ from six.moves.urllib.parse import urljoin import sys -sys.path.append('c:\AngelSmartApi\SmartApi') import csv import json import dateutil.parser @@ -243,12 +242,13 @@ def generateSession(self,clientCode,password): id=user['data']['clientcode'] #id='D88311' - print(id) + # + #print(id) self.setUserId(id) user['data']['jwtToken']="Bearer "+jwtToken user['data']['refreshToken']=refreshToken - print("USER",user) + #print("USER",user) return user def terminateSession(self,clientCode): diff --git a/SmartApi/version.py b/SmartApi/version.py index 55bbe6a..5d371db 100644 --- a/SmartApi/version.py +++ b/SmartApi/version.py @@ -2,7 +2,7 @@ __description__ = "Angel Broking openApi integration" __url__ = "https://www.angelbroking.com/" __download_url__ = "https://github.com/angelbroking-github/smartapi-python" -__version__ = "1.0.2" +__version__ = "1.0.3" __author__ = "ab-smartapi" __token__ = "ab-smartapi" __author_email__ = "smartapi.sdk@gmail.com" diff --git a/example/sample.py b/example/sample.py index 1d5c4f3..eb9f1fb 100644 --- a/example/sample.py +++ b/example/sample.py @@ -1,5 +1,5 @@ # package import statement -from smartapi import SmartConnect +from smartapi.smartConnect import SmartConnect obj=SmartConnect() #login api call diff --git a/setup.py b/setup.py index 03f07aa..bac95ef 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ setup( name="smartapi-python", - version="1.0.2", + version="1.0.3", author="ab-smartapi", author_email="smartapi.sdk@gmail.com", description="Angel Broking openApi integration", diff --git a/test/test.py b/test/test.py index c09ab2d..5701eae 100644 --- a/test/test.py +++ b/test/test.py @@ -5,13 +5,12 @@ #print(dir) #paths=dir.split("\") -sys.path.append(dir + "\SmartApi") +sys.path.append(dir + "\smartapi") #print(sys.path) -from smartapi import SmartConnect +from smartapi.smartConnect import SmartConnect -smartApi = -SmartConnect() +smartApi = SmartConnect() login = smartApi.generateSession('D88311', 'Angel@444') print(login) @@ -73,7 +72,7 @@ smartApi.convertPosition(params) smartApi.terminateSession('D88311') -from smartapi import SmartSocket +from smartapi.smartSocket import SmartSocket FEED_TOKEN='1731759952' CLIENT_CODE='S212741' token=None From ff144d3762bd3966e23c0df04bf110097ad73029 Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Mon, 30 Nov 2020 20:12:12 +0530 Subject: [PATCH 13/49] Changes in import statement and version --- SmartApi/smartConnect.py | 2 -- SmartApi/version.py | 2 +- example/sample.py | 2 +- setup.py | 2 +- test/test.py | 7 +++---- 5 files changed, 6 insertions(+), 9 deletions(-) diff --git a/SmartApi/smartConnect.py b/SmartApi/smartConnect.py index 8610d25..61aa61b 100644 --- a/SmartApi/smartConnect.py +++ b/SmartApi/smartConnect.py @@ -1,7 +1,5 @@ from six.moves.urllib.parse import urljoin import sys - -sys.path.append('c:\AngelSmartApi\SmartApi') import csv import json import dateutil.parser diff --git a/SmartApi/version.py b/SmartApi/version.py index 55bbe6a..5d371db 100644 --- a/SmartApi/version.py +++ b/SmartApi/version.py @@ -2,7 +2,7 @@ __description__ = "Angel Broking openApi integration" __url__ = "https://www.angelbroking.com/" __download_url__ = "https://github.com/angelbroking-github/smartapi-python" -__version__ = "1.0.2" +__version__ = "1.0.3" __author__ = "ab-smartapi" __token__ = "ab-smartapi" __author_email__ = "smartapi.sdk@gmail.com" diff --git a/example/sample.py b/example/sample.py index 1d5c4f3..eb9f1fb 100644 --- a/example/sample.py +++ b/example/sample.py @@ -1,5 +1,5 @@ # package import statement -from smartapi import SmartConnect +from smartapi.smartConnect import SmartConnect obj=SmartConnect() #login api call diff --git a/setup.py b/setup.py index 03f07aa..bac95ef 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ setup( name="smartapi-python", - version="1.0.2", + version="1.0.3", author="ab-smartapi", author_email="smartapi.sdk@gmail.com", description="Angel Broking openApi integration", diff --git a/test/test.py b/test/test.py index c09ab2d..bbd1838 100644 --- a/test/test.py +++ b/test/test.py @@ -8,10 +8,9 @@ sys.path.append(dir + "\SmartApi") #print(sys.path) -from smartapi import SmartConnect +from smartapi.smartConnect import SmartConnect -smartApi = -SmartConnect() +smartApi =SmartConnect() login = smartApi.generateSession('D88311', 'Angel@444') print(login) @@ -73,7 +72,7 @@ smartApi.convertPosition(params) smartApi.terminateSession('D88311') -from smartapi import SmartSocket +from smartapi.smartSocket import SmartSocket FEED_TOKEN='1731759952' CLIENT_CODE='S212741' token=None From c230c9efafdc8e7c4ba4c9caabee58de7c61ae6c Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Mon, 30 Nov 2020 20:18:49 +0530 Subject: [PATCH 14/49] Changes in readme --- README.md | 4 ++-- .../smartExceptions.cpython-36.pyc | Bin 3677 -> 3677 bytes SmartApi/__pycache__/version.cpython-36.pyc | Bin 480 -> 480 bytes 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c008a48..c8d39ef 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ pip install smartapi-python ```python # package import statement -from smartapi import SmartConnect +from smartapi.smartConnect import SmartConnect #create object of call obj=SmartConnect() @@ -55,7 +55,7 @@ except Exception as e: print("Logout failed: {}".format(e.message)) #websocket -from smartapi import SmartSocket +from smartapi.smartSocket import SmartSocket FEED_TOKEN= "your feed token" CLIENT_CODE="your client code" token="channel you want the information of" #"nse_cm|2885&nse_cm|1594&nse_cm|11536" diff --git a/SmartApi/__pycache__/smartExceptions.cpython-36.pyc b/SmartApi/__pycache__/smartExceptions.cpython-36.pyc index 8f9b5aa985bb0e1a1e0bb9b191002e1c45efda26..0abc8e087c8daca464e62acd1f3d0e6a089aeb77 100644 GIT binary patch delta 16 XcmcaBb61Aln3tF9-n%0k*~9n%Gv5XM delta 16 XcmcaBb61Aln3tDpDeKCO>|uNWEK>x) diff --git a/SmartApi/__pycache__/version.cpython-36.pyc b/SmartApi/__pycache__/version.cpython-36.pyc index 289b8a749518b7cceada335149ee19d1674de2b2..484ba97bb29333756e40468e7b7b97e8aa853697 100644 GIT binary patch delta 20 ccmaFB{D7I=n3tE!g5~H$_FIg`6CeEp06&}uJpcdz delta 20 ccmaFB{D7I=n3tDpE7Qt}?6(*VCqDWI07K&kng9R* From 7dbc0ff82fc5f3f8c2d1d928718be35757ebe4e1 Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Mon, 30 Nov 2020 20:21:08 +0530 Subject: [PATCH 15/49] changes in version --- SmartApi/version.py | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SmartApi/version.py b/SmartApi/version.py index 5d371db..df813ff 100644 --- a/SmartApi/version.py +++ b/SmartApi/version.py @@ -2,7 +2,7 @@ __description__ = "Angel Broking openApi integration" __url__ = "https://www.angelbroking.com/" __download_url__ = "https://github.com/angelbroking-github/smartapi-python" -__version__ = "1.0.3" +__version__ = "1.0.3.1" __author__ = "ab-smartapi" __token__ = "ab-smartapi" __author_email__ = "smartapi.sdk@gmail.com" diff --git a/setup.py b/setup.py index bac95ef..a4eeb3a 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ setup( name="smartapi-python", - version="1.0.3", + version="1.0.3.1", author="ab-smartapi", author_email="smartapi.sdk@gmail.com", description="Angel Broking openApi integration", From 42b4c25953d7380dbc1dd91b46aaa3dba602d063 Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Mon, 30 Nov 2020 20:30:56 +0530 Subject: [PATCH 16/49] bugs resolved --- SmartApi/smartConnect.py | 8 -------- SmartApi/version.py | 2 +- setup.py | 2 +- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/SmartApi/smartConnect.py b/SmartApi/smartConnect.py index 61aa61b..2900dd4 100644 --- a/SmartApi/smartConnect.py +++ b/SmartApi/smartConnect.py @@ -274,15 +274,7 @@ def renewAccessToken(self): if "jwtToken" in response: tokenSet['jwtToken']=response['data']['jwtToken'] -<<<<<<< HEAD -<<<<<<< HEAD tokenSet['clientcode']=self. userId -======= - tokenSet['clientcode']=self.userId ->>>>>>> d8cd1ced0e9e79452791072bec4213ec85e370b1 -======= - tokenSet['clientcode']=self. userId ->>>>>>> develop tokenSet['refreshToken']=response['data']["refreshToken"] return tokenSet diff --git a/SmartApi/version.py b/SmartApi/version.py index df813ff..9dac5cd 100644 --- a/SmartApi/version.py +++ b/SmartApi/version.py @@ -2,7 +2,7 @@ __description__ = "Angel Broking openApi integration" __url__ = "https://www.angelbroking.com/" __download_url__ = "https://github.com/angelbroking-github/smartapi-python" -__version__ = "1.0.3.1" +__version__ = "1.0.3.2" __author__ = "ab-smartapi" __token__ = "ab-smartapi" __author_email__ = "smartapi.sdk@gmail.com" diff --git a/setup.py b/setup.py index a4eeb3a..3035b70 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ setup( name="smartapi-python", - version="1.0.3.1", + version="1.0.3.2", author="ab-smartapi", author_email="smartapi.sdk@gmail.com", description="Angel Broking openApi integration", From 064faf6ddf31f9e7920b97f0c02408af983a50ca Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Mon, 30 Nov 2020 20:35:31 +0530 Subject: [PATCH 17/49] bugs resolved --- SmartApi/smartConnect.py | 2 +- SmartApi/version.py | 2 +- setup.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/SmartApi/smartConnect.py b/SmartApi/smartConnect.py index 2900dd4..de9fed1 100644 --- a/SmartApi/smartConnect.py +++ b/SmartApi/smartConnect.py @@ -94,7 +94,7 @@ def __init__(self, api_key=None, access_token=None, refresh_token=None, userId=N self.refresh_token = refresh_token self.userId = userId self.proxies = proxies if proxies else {} - self.root = root or self._loginUrl + self.root = root or self._login_url self.timeout = timeout or self._default_timeout if pool: diff --git a/SmartApi/version.py b/SmartApi/version.py index 9dac5cd..b5098a7 100644 --- a/SmartApi/version.py +++ b/SmartApi/version.py @@ -2,7 +2,7 @@ __description__ = "Angel Broking openApi integration" __url__ = "https://www.angelbroking.com/" __download_url__ = "https://github.com/angelbroking-github/smartapi-python" -__version__ = "1.0.3.2" +__version__ = "1.0.3.3" __author__ = "ab-smartapi" __token__ = "ab-smartapi" __author_email__ = "smartapi.sdk@gmail.com" diff --git a/setup.py b/setup.py index 3035b70..863bf49 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ setup( name="smartapi-python", - version="1.0.3.2", + version="1.0.3.3", author="ab-smartapi", author_email="smartapi.sdk@gmail.com", description="Angel Broking openApi integration", From 75447d4039182f5715c0f902af443a4ba7674152 Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Mon, 30 Nov 2020 21:00:43 +0530 Subject: [PATCH 18/49] changes in root variable --- .../__pycache__/smartConnect.cpython-36.pyc | Bin 10823 -> 10665 bytes SmartApi/smartConnect.py | 2 +- SmartApi/version.py | 2 +- setup.py | 2 +- test/test.py | 4 ++-- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/SmartApi/__pycache__/smartConnect.cpython-36.pyc b/SmartApi/__pycache__/smartConnect.cpython-36.pyc index 87d7f6cf32a2cff265de5513bc7f0d91c811bc0f..0c5a599335c27382a8335818536f07de4a9b7e6e 100644 GIT binary patch delta 822 zcmYk)U2IEX9LMqVZ@c!`+P&yz?Z#-kv2JwOtG%-^n|Is1JVtf>)wE7qnF^UijdA6M zzr>Ar2^YBSt|cx+A|Y{0BHk{DM7-R|g1^IslRVGooAW%+$;ruiJaTV1+vsxT|8zYH z_cUqRJMF*ACfzIJ*j<^RfebB4is(;U42!auT9wt*rfjBp%5LgV4pUv}rt{Q1)BHq% za+>8*E^*vyxRQmc@ZV#LRFSz@tcp!bREcOa<|p0Coh((Qq{Z|^S!}^MQso00@?f9Q zV2^puS(O)-VJ+zRD6gvp>4oF?q>)I+Q(IZ5R=UEybl#37@WIDV$&G?)Cz3Gpqvb02%E%g12$ue#7b<%HgOfUV~4mJJ25OaVg#dN6Lw*@*o-~c zE4DykpV*2q>=)Z`0AX)Y7@tfZiKiw)(R4C*$a*2qu7@Yn=}hjsKA&h0+w*@= znyKIk%!r&j_v4nOcT~R86x> zjdz>u9xsd`CPux`-Mj8TU}9q8#U@^v5ED^@iF)Uy(apY0G}%k%WZvJCIp^e@yvaO> zKN&CfR#&^{mLDe$^eM_4<$sTz^Dw_Ne{+EX(v&O-qLpmZY{I76G8Gv+D(1g^s}z;i zT$QM@bO@)VOSmlE!fojh9!qbgS`=4V(IxVu~B5O8^gSFBQ9bDKXBRv4STSc zQzwd9jA9?hF6h{gA31g701ooj7=FSbb~6rRjNO7GILh|m7>={Oh+~}X!wH;Zx8f9j zX1C!q1lx}@m|zER7U$UQNMMp3L=xxO9Y_I14nt6Jf!&EIOtZTXdg_Dz^mch#az~ z`6&hNerYCZmH)0=qE7j;NqGhXT?F73esp zKj@^q+V+`*EQIe-O0JI#({4E#3A=?ekv9zUL|!YGBI7n+!^-b Date: Tue, 1 Dec 2020 11:17:56 +0530 Subject: [PATCH 19/49] Updated code --- README.md | 6 +++--- .../__pycache__/smartConnect.cpython-36.pyc | Bin 10665 -> 10666 bytes SmartApi/smartConnect.py | 2 +- example/sample.py | 2 +- test/test.py | 12 ++++++------ 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index c8d39ef..0e07ded 100644 --- a/README.md +++ b/README.md @@ -17,11 +17,11 @@ pip install smartapi-python from smartapi.smartConnect import SmartConnect #create object of call -obj=SmartConnect() +obj=SmartConnect(api_key="your api key") #login api call -data = obj.generateSession("D88311","Angel@444") +data = obj.generateSession("Your Client ID","Your Password") refreshToken= data['data']['refreshToken'] #fetch User Profile @@ -57,7 +57,7 @@ except Exception as e: #websocket from smartapi.smartSocket import SmartSocket FEED_TOKEN= "your feed token" -CLIENT_CODE="your client code" +CLIENT_CODE="your client Id" token="channel you want the information of" #"nse_cm|2885&nse_cm|1594&nse_cm|11536" ss = SmartSocket(FEED_TOKEN, CLIENT_CODE) diff --git a/SmartApi/__pycache__/smartConnect.cpython-36.pyc b/SmartApi/__pycache__/smartConnect.cpython-36.pyc index 0c5a599335c27382a8335818536f07de4a9b7e6e..cc8f43153212531ee550407f62b3ee31d0fca763 100644 GIT binary patch delta 568 zcmY+9&2G~`6ov1d1`{W7?AT6PH)-pnZ3JwA4X{OGgM{RYrfg89o6T5?gfZ%mW*RA$ z*ttT=h6OJGI~0irK)@654s3Y>#2se?vh4Akd*+;PJ|>?M`>x|O?gigpKK^W9J2+Xs zch2Stq^Fy7L$}D%4&Bsk)lzk3s|K%4<)}8*Kh(9$zE1YVe6>fm6v``5xzuuq)jH?ihxl>HooXF%&sxWJ&Fn}PzPLhhwI|1?gxT-@}V5jb`{sB ze#yQCo~#Q4Y15!UP8%`)K9~P7rL>cZ>OY`C1hkvZ*ITv}Ch#C1s%pg1hsA~tRml6j z2&%(zDHf=L1ZemV?gImwtYJnBQ(eSpv~MoAKynkfJ-+NdJx!tz{soyqk}m)N delta 570 zcmY+9%We}f6ozeg7&4Q%^<0v6(x#oZDYpd@V#5N&mJJfpMD(&jl}-r8Ev>x&WE;2MA&}s{ zfh&Ww2~4C`psORtVfOQk`O* zXT)9JZP=XZq#&^O5AGccT3o>FBaC~9)nM2#iv*$|*RM{y4^PW+emcn?j7E?0YW(#1 l_?fynU2rk Date: Tue, 1 Dec 2020 18:20:57 +0530 Subject: [PATCH 20/49] updated Readme file --- README.md | 2 +- SmartApi/version.py | 2 +- example/sample.py | 2 +- setup.py | 2 +- test/test.py | 19 ++++++------------- 5 files changed, 10 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 0e07ded..080f2f4 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ except Exception as e: #logout try: - logout=obj.terminateSession('D88311') + logout=obj.terminateSession('Your Client Id') print("Logout Successfull") except Exception as e: print("Logout failed: {}".format(e.message)) diff --git a/SmartApi/version.py b/SmartApi/version.py index 899adde..0d3b5d4 100644 --- a/SmartApi/version.py +++ b/SmartApi/version.py @@ -2,7 +2,7 @@ __description__ = "Angel Broking openApi integration" __url__ = "https://www.angelbroking.com/" __download_url__ = "https://github.com/angelbroking-github/smartapi-python" -__version__ = "1.0.3.4" +__version__ = "1.0.4" __author__ = "ab-smartapi" __token__ = "ab-smartapi" __author_email__ = "smartapi.sdk@gmail.com" diff --git a/example/sample.py b/example/sample.py index 182f99d..1b9f704 100644 --- a/example/sample.py +++ b/example/sample.py @@ -33,7 +33,7 @@ #logout try: - logout=obj.terminateSession('D88311') + logout=obj.terminateSession('Your Client Id') print("Logout Successfull") except Exception as e: print("Logout failed: {}".format(e.message)) \ No newline at end of file diff --git a/setup.py b/setup.py index af44515..0b29e51 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ setup( name="smartapi-python", - version="1.0.3.4", + version="1.0.4", author="ab-smartapi", author_email="smartapi.sdk@gmail.com", description="Angel Broking openApi integration", diff --git a/test/test.py b/test/test.py index 15daa61..1f7279a 100644 --- a/test/test.py +++ b/test/test.py @@ -1,22 +1,15 @@ import sys import os -dir = os.getcwd() -#print(dir) -#paths=dir.split("\") - -sys.path.append(dir + "\SmartApi") -#print(sys.path) - from smartConnect import SmartConnect -smartApi =SmartConnect(api_key="smartapi_key") +smartApi =SmartConnect(api_key="Your Api Key") -login = smartApi.generateSession('Your client id', 'Password') +login = smartApi.generateSession('Your Client Id', 'Your Password') print(login) refreshToken = login['data']['refreshToken'] smartApi.getProfile(refreshToken) -#smartApi.generateToken(refreshToken) +smartApi.generateToken(refreshToken) orderparams = { "variety": "NORMAL", "tradingsymbol": "SBIN-EQ", @@ -70,11 +63,11 @@ } smartApi.convertPosition(params) -smartApi.terminateSession('Your client code') +smartApi.terminateSession("Your Client Id") from smartapi.smartSocket import SmartSocket -FEED_TOKEN='feedToken' #'1731759952' -CLIENT_CODE='Your client id' #'S212741' +FEED_TOKEN="Your Feed Token" +CLIENT_CODE="Your Client Id" token=None ss = SmartSocket(FEED_TOKEN, CLIENT_CODE) def on_tick(ws, tick): From e5e1457137da59ed7959eb90269e94bbca0c9c01 Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Thu, 3 Dec 2020 11:53:43 +0530 Subject: [PATCH 21/49] changes in init.py file and readme file --- README.md | 7 ++++--- SmartApi/__init__.py | 3 +-- SmartApi/version.py | 2 +- example/sample.py | 2 +- requirements_dev.txt | 2 +- setup.py | 2 +- test/test.py | 15 ++++++++++----- 7 files changed, 19 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 080f2f4..3805a8c 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,8 @@ pip install smartapi-python ```python # package import statement -from smartapi.smartConnect import SmartConnect +from smartapi import SmartConnect #or from smartapi.smartConnect import SmartConnect +#import smartapi.smartExceptions(for smartExceptions) #create object of call obj=SmartConnect(api_key="your api key") @@ -54,8 +55,8 @@ try: except Exception as e: print("Logout failed: {}".format(e.message)) -#websocket -from smartapi.smartSocket import SmartSocket +##------websocket------ +from smartapi import SmartSocket #or from smartapi.smartSocket import SmartSocket FEED_TOKEN= "your feed token" CLIENT_CODE="your client Id" token="channel you want the information of" #"nse_cm|2885&nse_cm|1594&nse_cm|11536" diff --git a/SmartApi/__init__.py b/SmartApi/__init__.py index f5955af..ab3c672 100644 --- a/SmartApi/__init__.py +++ b/SmartApi/__init__.py @@ -1,10 +1,9 @@ from __future__ import unicode_literals,absolute_import -from smartapi import smartExceptions from smartapi.smartConnect import SmartConnect from smartapi.smartSocket import SmartSocket -__all__ = ["smartExceptions","SmartConnect","SmartSocket"] +__all__ = ["SmartConnect","SmartSocket"] diff --git a/SmartApi/version.py b/SmartApi/version.py index 0d3b5d4..bb1956b 100644 --- a/SmartApi/version.py +++ b/SmartApi/version.py @@ -2,7 +2,7 @@ __description__ = "Angel Broking openApi integration" __url__ = "https://www.angelbroking.com/" __download_url__ = "https://github.com/angelbroking-github/smartapi-python" -__version__ = "1.0.4" +__version__ = "1.0.5" __author__ = "ab-smartapi" __token__ = "ab-smartapi" __author_email__ = "smartapi.sdk@gmail.com" diff --git a/example/sample.py b/example/sample.py index 1b9f704..7764fd6 100644 --- a/example/sample.py +++ b/example/sample.py @@ -1,5 +1,5 @@ # package import statement -from smartapi.smartConnect import SmartConnect +from smartapi.smartConnect import SmartConnect #from smartapi import SmartConnect obj=SmartConnect() #login api call diff --git a/requirements_dev.txt b/requirements_dev.txt index c1693f2..84c6643 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -1,2 +1,2 @@ requests>=2.24.0 -twine>=1.13.0 \ No newline at end of file +twine>=1.13.0 diff --git a/setup.py b/setup.py index 0b29e51..01cf503 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ setup( name="smartapi-python", - version="1.0.4", + version="1.0.5", author="ab-smartapi", author_email="smartapi.sdk@gmail.com", description="Angel Broking openApi integration", diff --git a/test/test.py b/test/test.py index 1f7279a..b536a0e 100644 --- a/test/test.py +++ b/test/test.py @@ -1,7 +1,10 @@ -import sys -import os -from smartConnect import SmartConnect +from smartapi import SmartConnect + +#---------for smartExceptions--------- +#import smartapi.smartExceptions +#or +#from smartapi import smartExceptions smartApi =SmartConnect(api_key="Your Api Key") @@ -63,9 +66,11 @@ } smartApi.convertPosition(params) -smartApi.terminateSession("Your Client Id") +smartApi.terminateSession('S212741') + +## Websocket Programming -from smartapi.smartSocket import SmartSocket +from smartapi import SmartSocket FEED_TOKEN="Your Feed Token" CLIENT_CODE="Your Client Id" token=None From 260fc762ccfbf82f00944f199733bc757d1ed6e6 Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Tue, 8 Dec 2020 16:53:49 +0530 Subject: [PATCH 22/49] getFeedToken() function added, Changes in import statement for websocket --- README.md | 8 +- SmartApi/__init__.py | 4 +- .../__pycache__/smartConnect.cpython-36.pyc | Bin 10666 -> 10666 bytes SmartApi/smartConnect.py | 19 +++- SmartApi/version.py | 4 +- SmartApi/{smartSocket.py => webSocket.py} | 95 ++++++++++++++++-- setup.py | 3 +- test/test.py | 10 +- 8 files changed, 115 insertions(+), 28 deletions(-) rename SmartApi/{smartSocket.py => webSocket.py} (77%) diff --git a/README.md b/README.md index 3805a8c..fe16cc4 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,9 @@ obj=SmartConnect(api_key="your api key") data = obj.generateSession("Your Client ID","Your Password") refreshToken= data['data']['refreshToken'] +#fetch the feedtoken +feedToken=obj.getFeedToken() + #fetch User Profile userProfile= obj.getProfile(refreshToken) #place order @@ -56,7 +59,7 @@ except Exception as e: print("Logout failed: {}".format(e.message)) ##------websocket------ -from smartapi import SmartSocket #or from smartapi.smartSocket import SmartSocket +from smartapi import WebSocket #or from smartapi.smartSocket import SmartSocket FEED_TOKEN= "your feed token" CLIENT_CODE="your client Id" token="channel you want the information of" #"nse_cm|2885&nse_cm|1594&nse_cm|11536" @@ -80,7 +83,6 @@ ss.on_close = on_close ss.connect( ) -License -MIT + diff --git a/SmartApi/__init__.py b/SmartApi/__init__.py index ab3c672..4ddea18 100644 --- a/SmartApi/__init__.py +++ b/SmartApi/__init__.py @@ -1,9 +1,9 @@ from __future__ import unicode_literals,absolute_import from smartapi.smartConnect import SmartConnect -from smartapi.smartSocket import SmartSocket +from smartapi.webSocket import WebSocket -__all__ = ["SmartConnect","SmartSocket"] +__all__ = ["SmartConnect","WebSocket"] diff --git a/SmartApi/__pycache__/smartConnect.cpython-36.pyc b/SmartApi/__pycache__/smartConnect.cpython-36.pyc index cc8f43153212531ee550407f62b3ee31d0fca763..7a7be233af39fa670bae0a86f2d1555df0d14b7d 100644 GIT binary patch delta 16 XcmZ1#yegR8n3tDpLd}Vd?29!4FXRQW delta 16 XcmZ1#yegR8n3tE!MEK}N_Qje2D%%9< diff --git a/SmartApi/smartConnect.py b/SmartApi/smartConnect.py index 10d3dbc..b08a3a4 100644 --- a/SmartApi/smartConnect.py +++ b/SmartApi/smartConnect.py @@ -85,13 +85,14 @@ class SmartConnect(object): "api.convert.position": "/rest/secure/angelbroking/order/v1/convertPosition" } - def __init__(self, api_key=None, access_token=None, refresh_token=None, userId=None, root=None, debug=False, timeout=None, proxies=None, pool=None, disable_ssl=False): + def __init__(self, api_key=None, access_token=None, refresh_token=None,feed_token=None, userId=None, root=None, debug=False, timeout=None, proxies=None, pool=None, disable_ssl=False): self.debug = debug self.api_key = api_key self.session_expiry_hook = None self.disable_ssl = disable_ssl self.access_token = access_token self.refresh_token = refresh_token + self.feed_token = feed_token self.userId = userId self.proxies = proxies if proxies else {} self.root = root or self._rootUrl @@ -126,6 +127,14 @@ def setAccessToken(self, access_token): def setRefreshToken(self, refresh_token): self.refresh_token = refresh_token + + def setFeedToken(self,feedToken): + + self.feed_token=feedToken + + def getfeedToken(self): + return self.feed_token + def login_url(self): """Get the remote login url to which a user should be redirected to initiate the login flow.""" @@ -236,16 +245,17 @@ def generateSession(self,clientCode,password): jwtToken=loginResultObject['data']['jwtToken'] self.setAccessToken(jwtToken) refreshToken=loginResultObject['data']['refreshToken'] + feedToken=loginResultObject['data']['feedToken'] self.setRefreshToken(refreshToken) + self.setFeedToken(feedToken) user=self.getProfile(refreshToken) id=user['data']['clientcode'] #id='D88311' - print(id) - self.setUserId(id) user['data']['jwtToken']="Bearer "+jwtToken user['data']['refreshToken']=refreshToken + print("USER",user) return user @@ -256,7 +266,10 @@ def terminateSession(self,clientCode): def generateToken(self,refresh_token): response=self._postRequest('api.token',{"refreshToken":refresh_token}) jwtToken=response['data']['jwtToken'] + feedToken=response['data']['feedToken'] + self.setFeedToken(feedToken) self.setAccessToken(jwtToken) + return response def renewAccessToken(self): diff --git a/SmartApi/version.py b/SmartApi/version.py index bb1956b..ec95919 100644 --- a/SmartApi/version.py +++ b/SmartApi/version.py @@ -2,11 +2,11 @@ __description__ = "Angel Broking openApi integration" __url__ = "https://www.angelbroking.com/" __download_url__ = "https://github.com/angelbroking-github/smartapi-python" -__version__ = "1.0.5" +__version__ = "1.0.5.1" __author__ = "ab-smartapi" __token__ = "ab-smartapi" __author_email__ = "smartapi.sdk@gmail.com" -__license__ = "MIT" + # [pypi] # username = __token__ diff --git a/SmartApi/smartSocket.py b/SmartApi/webSocket.py similarity index 77% rename from SmartApi/smartSocket.py rename to SmartApi/webSocket.py index 5044463..14e40ca 100644 --- a/SmartApi/smartSocket.py +++ b/SmartApi/webSocket.py @@ -7,6 +7,7 @@ import logging import threading import base64 +import zlib from datetime import datetime from twisted.internet import reactor, ssl from twisted.python import log as twisted_log @@ -15,6 +16,15 @@ class SmartSocketClientProtocol(WebSocketClientProtocol): + PING_INTERVAL = 2.5 + KEEPALIVE_INTERVAL = 5 + + _ping_message = "" + _next_ping = None + _next_pong_check = None + _last_pong_time = None + _last_ping_time = None + def __init__(self, *args, **kwargs): super(SmartSocketClientProtocol,self).__init__(*args,**kwargs) @@ -26,13 +36,20 @@ def onConnect(self, response): # noqa self.factory.on_connect(self, response) def onOpen(self): + # send ping + self._loop_ping() + # init last pong check after X seconds + self._loop_pong_check() + if self.factory.on_open: self.factory.on_open(self) + def onMessage(self, payload, is_binary): # noqa #print("""Called when text or binary message is received.""",payload,is_binary) if self.factory.on_message: self.factory.on_message(self, payload, is_binary) + def onClose(self, was_clean, code, reason): # noqa """Called when connection is closed.""" @@ -42,6 +59,61 @@ def onClose(self, was_clean, code, reason): # noqa if self.factory.on_close: self.factory.on_close(self, code, reason) + # Cancel next ping and timer + self._last_ping_time = None + self._last_pong_time = None + + if self._next_ping: + self._next_ping.cancel() + + if self._next_pong_check: + self._next_pong_check.cancel() + + def onPong(self, response): # noqa + """Called when pong message is received.""" + if self._last_pong_time and self.factory.debug: + log.debug("last pong was {} seconds back.".format(time.time() - self._last_pong_time)) + + self._last_pong_time = time.time() + + if self.factory.debug: + log.debug("pong => {}".format(response)) + + """ + Custom helper and exposed methods. + """ + def _loop_ping(self): # noqa + """Start a ping loop where it sends ping message every X seconds.""" + if self.factory.debug: + log.debug("ping => {}".format(self._ping_message)) + if self._last_ping_time: + log.debug("last ping was {} seconds back.".format(time.time() - self._last_ping_time)) + + # Set current time as last ping time + self._last_ping_time = time.time() + # Send a ping message to server + self.sendPing(self._ping_message) + + # Call self after X seconds + self._next_ping = self.factory.reactor.callLater(self.PING_INTERVAL, self._loop_ping) + + def _loop_pong_check(self): + """ + Timer sortof to check if connection is still there. + Checks last pong message time and disconnects the existing connection to make sure it doesn't become a ghost connection. + """ + if self._last_pong_time: + # No pong message since long time, so init reconnect + last_pong_diff = time.time() - self._last_pong_time + if last_pong_diff > (2 * self.PING_INTERVAL): + if self.factory.debug: + log.debug("Last pong was {} seconds ago. So dropping connection to reconnect.".format( + last_pong_diff)) + # drop existing connection to avoid ghost connection + self.dropConnection(abort=True) + + # Call self after X seconds + self._next_pong_check = self.factory.reactor.callLater(self.PING_INTERVAL, self._loop_pong_check) class SmartSocketClientFactory(WebSocketClientFactory): protocol = SmartSocketClientProtocol @@ -141,6 +213,7 @@ def is_connected(self): return True else: return False + def _close(self, code=None, reason=None): #print("Close the WebSocket connection.") if self.ws: @@ -158,9 +231,8 @@ def stop(self): reactor.stop() def send_request(self,token): - #print('Request Send') - strwatchlistscrips = token # "nse_cm|2885&nse_cm|1594&nse_cm|11536" - #token_scripts= token //dynamic call + strwatchlistscrips = token #dynamic call + try: #print("Inside") request={"task":"cn","channel":"","token":self.feed_token,"user":self.client_code,"acctid":self.client_code} @@ -168,7 +240,7 @@ def send_request(self,token): six.b(json.dumps(request)) ) #print(request) - request={"task":"cn","channel":strwatchlistscrips,"token":self.feed_token,"user":self.client_code,"acctid":self.client_code} + request={"task":"mw","channel":strwatchlistscrips,"token":self.feed_token,"user":self.client_code,"acctid":self.client_code} #print(request) #request={"task":"cn","channel":token_scripts,"token":self.feed_token,"user":self.client_code,"acctid":self.client_code} //dynamic call self.ws.sendMessage( @@ -187,14 +259,14 @@ def _on_connect(self, ws, response): def _on_close(self, ws, code, reason): """Call `on_close` callback when connection is closed.""" - print("Connection closed: {} - {}".format(code, str(reason))) + log.debug("Connection closed: {} - {}".format(code, str(reason))) if self.on_close: self.on_close(self, code, reason) def _on_error(self, ws, code, reason): """Call `on_error` callback when connection throws an error.""" - print("Connection error: {} - {}".format(code, str(reason))) + log.debug("Connection error: {} - {}".format(code, str(reason))) if self.on_error: self.on_error(self, code, reason) @@ -221,13 +293,16 @@ def _parse_text_message(self, payload): # Decode unicode data if not six.PY2 and type(payload) == bytes: payload = payload.decode("utf-8") - print("PAYLOAD",payload) + data =base64.b64decode(payload) - print("DATA",data) + + try: - data = json.loads(payload) - print("DATA",data) + data=zlib.decompress(data) + print(data.decode("utf-8")) + except ValueError: + return def _parse_binary(self, bin): diff --git a/setup.py b/setup.py index 01cf503..d60474f 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ setup( name="smartapi-python", - version="1.0.5", + version="1.0.5.1", author="ab-smartapi", author_email="smartapi.sdk@gmail.com", description="Angel Broking openApi integration", @@ -28,7 +28,6 @@ "Intended Audience :: Financial and Insurance Industry", "Programming Language :: Python", "Natural Language :: English", - "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", diff --git a/test/test.py b/test/test.py index b536a0e..2698a59 100644 --- a/test/test.py +++ b/test/test.py @@ -1,4 +1,3 @@ - from smartapi import SmartConnect #---------for smartExceptions--------- @@ -11,6 +10,7 @@ login = smartApi.generateSession('Your Client Id', 'Your Password') print(login) refreshToken = login['data']['refreshToken'] +feedToken = smartApi.getfeedToken() smartApi.getProfile(refreshToken) smartApi.generateToken(refreshToken) orderparams = { @@ -66,11 +66,11 @@ } smartApi.convertPosition(params) -smartApi.terminateSession('S212741') +smartApi.terminateSession('Your Client Id') ## Websocket Programming -from smartapi import SmartSocket +from smartapi import WebSocket FEED_TOKEN="Your Feed Token" CLIENT_CODE="Your Client Id" token=None @@ -88,6 +88,4 @@ def on_close(ws, code, reason): ss.on_connect = on_connect ss.on_close = on_close -ss.connect( ) - - +ss.connect( ) \ No newline at end of file From ea49f8ba177d99f84e450b7523b0e24373ab3df8 Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Tue, 8 Dec 2020 17:01:06 +0530 Subject: [PATCH 23/49] getFeedToken() function added, Changes in import statement for websocket --- SmartApi/version.py | 2 +- SmartApi/webSocket.py | 2 +- setup.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/SmartApi/version.py b/SmartApi/version.py index ec95919..4cb9a7b 100644 --- a/SmartApi/version.py +++ b/SmartApi/version.py @@ -2,7 +2,7 @@ __description__ = "Angel Broking openApi integration" __url__ = "https://www.angelbroking.com/" __download_url__ = "https://github.com/angelbroking-github/smartapi-python" -__version__ = "1.0.5.1" +__version__ = "1.0.5.2" __author__ = "ab-smartapi" __token__ = "ab-smartapi" __author_email__ = "smartapi.sdk@gmail.com" diff --git a/SmartApi/webSocket.py b/SmartApi/webSocket.py index 14e40ca..68ffc5b 100644 --- a/SmartApi/webSocket.py +++ b/SmartApi/webSocket.py @@ -132,7 +132,7 @@ def __init__(self, *args, **kwargs): super(SmartSocketClientFactory, self).__init__(*args, **kwargs) -class SmartSocket(object): +class WebSocket(object): EXCHANGE_MAP = { "nse": 1, "nfo": 2, diff --git a/setup.py b/setup.py index d60474f..3d2bc62 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ setup( name="smartapi-python", - version="1.0.5.1", + version="1.0.5.2", author="ab-smartapi", author_email="smartapi.sdk@gmail.com", description="Angel Broking openApi integration", From 8fecc004e01e903c1bff295114f04ac971a82af4 Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Wed, 9 Dec 2020 19:18:58 +0530 Subject: [PATCH 24/49] Changes in import statement for websocket --- README.md | 4 ++-- SmartApi/version.py | 2 +- setup.py | 2 +- test/test.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index fe16cc4..037b33f 100644 --- a/README.md +++ b/README.md @@ -59,12 +59,12 @@ except Exception as e: print("Logout failed: {}".format(e.message)) ##------websocket------ -from smartapi import WebSocket #or from smartapi.smartSocket import SmartSocket +from smartapi import WebSocket FEED_TOKEN= "your feed token" CLIENT_CODE="your client Id" token="channel you want the information of" #"nse_cm|2885&nse_cm|1594&nse_cm|11536" -ss = SmartSocket(FEED_TOKEN, CLIENT_CODE) +ss = WebSocket(FEED_TOKEN, CLIENT_CODE) def on_tick(ws, tick): print("Ticks: {}".format(tick)) diff --git a/SmartApi/version.py b/SmartApi/version.py index 4cb9a7b..4aa5bd2 100644 --- a/SmartApi/version.py +++ b/SmartApi/version.py @@ -2,7 +2,7 @@ __description__ = "Angel Broking openApi integration" __url__ = "https://www.angelbroking.com/" __download_url__ = "https://github.com/angelbroking-github/smartapi-python" -__version__ = "1.0.5.2" +__version__ = "1.0.5.3" __author__ = "ab-smartapi" __token__ = "ab-smartapi" __author_email__ = "smartapi.sdk@gmail.com" diff --git a/setup.py b/setup.py index 3d2bc62..efb5061 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ setup( name="smartapi-python", - version="1.0.5.2", + version="1.0.5.3", author="ab-smartapi", author_email="smartapi.sdk@gmail.com", description="Angel Broking openApi integration", diff --git a/test/test.py b/test/test.py index 2698a59..6cef4ec 100644 --- a/test/test.py +++ b/test/test.py @@ -74,7 +74,7 @@ FEED_TOKEN="Your Feed Token" CLIENT_CODE="Your Client Id" token=None -ss = SmartSocket(FEED_TOKEN, CLIENT_CODE) +ss = WebSocket(FEED_TOKEN, CLIENT_CODE) def on_tick(ws, tick): print("Ticks: {}".format(tick)) def on_connect(ws, response): From 9765bcba2eb9f3d71489e7a3d9ff7205ba5d81e6 Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Thu, 10 Dec 2020 13:24:10 +0530 Subject: [PATCH 25/49] getfeedToken() --- README.md | 2 +- SmartApi/version.py | 2 +- setup.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 037b33f..a05e03d 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ data = obj.generateSession("Your Client ID","Your Password") refreshToken= data['data']['refreshToken'] #fetch the feedtoken -feedToken=obj.getFeedToken() +feedToken=obj.getfeedToken() #fetch User Profile userProfile= obj.getProfile(refreshToken) diff --git a/SmartApi/version.py b/SmartApi/version.py index 4aa5bd2..062b65e 100644 --- a/SmartApi/version.py +++ b/SmartApi/version.py @@ -2,7 +2,7 @@ __description__ = "Angel Broking openApi integration" __url__ = "https://www.angelbroking.com/" __download_url__ = "https://github.com/angelbroking-github/smartapi-python" -__version__ = "1.0.5.3" +__version__ = "1.0.5.4" __author__ = "ab-smartapi" __token__ = "ab-smartapi" __author_email__ = "smartapi.sdk@gmail.com" diff --git a/setup.py b/setup.py index efb5061..4e5489e 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ setup( name="smartapi-python", - version="1.0.5.3", + version="1.0.5.4", author="ab-smartapi", author_email="smartapi.sdk@gmail.com", description="Angel Broking openApi integration", From a9617cee63b0b3b634de4d62348666ddbb6d6eb9 Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Thu, 10 Dec 2020 14:48:14 +0530 Subject: [PATCH 26/49] bugs rectified --- SmartApi/version.py | 2 +- SmartApi/webSocket.py | 1 + setup.py | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/SmartApi/version.py b/SmartApi/version.py index 062b65e..07f66c0 100644 --- a/SmartApi/version.py +++ b/SmartApi/version.py @@ -2,7 +2,7 @@ __description__ = "Angel Broking openApi integration" __url__ = "https://www.angelbroking.com/" __download_url__ = "https://github.com/angelbroking-github/smartapi-python" -__version__ = "1.0.5.4" +__version__ = "1.0.5.5" __author__ = "ab-smartapi" __token__ = "ab-smartapi" __author_email__ = "smartapi.sdk@gmail.com" diff --git a/SmartApi/webSocket.py b/SmartApi/webSocket.py index 68ffc5b..b048246 100644 --- a/SmartApi/webSocket.py +++ b/SmartApi/webSocket.py @@ -14,6 +14,7 @@ from autobahn.twisted.websocket import WebSocketClientProtocol, \ WebSocketClientFactory, connectWS +log = logging.getLogger(__name__) class SmartSocketClientProtocol(WebSocketClientProtocol): PING_INTERVAL = 2.5 diff --git a/setup.py b/setup.py index 4e5489e..7ed8684 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ setup( name="smartapi-python", - version="1.0.5.4", + version="1.0.5.5", author="ab-smartapi", author_email="smartapi.sdk@gmail.com", description="Angel Broking openApi integration", From bd11f8a4b54216b72d94cb849fd8a8c1ccf6afea Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Fri, 11 Dec 2020 12:12:37 +0530 Subject: [PATCH 27/49] heartbeats added in websocket --- README.md | 2 +- SmartApi/version.py | 2 +- SmartApi/webSocket.py | 195 +++++++++++++++--------------------------- setup.py | 2 +- test/test.py | 20 ++++- 5 files changed, 88 insertions(+), 133 deletions(-) diff --git a/README.md b/README.md index a05e03d..df17c6f 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ try: except Exception as e: print("Logout failed: {}".format(e.message)) -##------websocket------ +## WebSocket from smartapi import WebSocket FEED_TOKEN= "your feed token" CLIENT_CODE="your client Id" diff --git a/SmartApi/version.py b/SmartApi/version.py index 07f66c0..5038776 100644 --- a/SmartApi/version.py +++ b/SmartApi/version.py @@ -2,7 +2,7 @@ __description__ = "Angel Broking openApi integration" __url__ = "https://www.angelbroking.com/" __download_url__ = "https://github.com/angelbroking-github/smartapi-python" -__version__ = "1.0.5.5" +__version__ = "1.0.6" __author__ = "ab-smartapi" __token__ = "ab-smartapi" __author_email__ = "smartapi.sdk@gmail.com" diff --git a/SmartApi/webSocket.py b/SmartApi/webSocket.py index b048246..adc9aff 100644 --- a/SmartApi/webSocket.py +++ b/SmartApi/webSocket.py @@ -17,14 +17,6 @@ log = logging.getLogger(__name__) class SmartSocketClientProtocol(WebSocketClientProtocol): - PING_INTERVAL = 2.5 - KEEPALIVE_INTERVAL = 5 - - _ping_message = "" - _next_ping = None - _next_pong_check = None - _last_pong_time = None - _last_ping_time = None def __init__(self, *args, **kwargs): super(SmartSocketClientProtocol,self).__init__(*args,**kwargs) @@ -37,11 +29,6 @@ def onConnect(self, response): # noqa self.factory.on_connect(self, response) def onOpen(self): - # send ping - self._loop_ping() - # init last pong check after X seconds - self._loop_pong_check() - if self.factory.on_open: self.factory.on_open(self) @@ -60,61 +47,7 @@ def onClose(self, was_clean, code, reason): # noqa if self.factory.on_close: self.factory.on_close(self, code, reason) - # Cancel next ping and timer - self._last_ping_time = None - self._last_pong_time = None - - if self._next_ping: - self._next_ping.cancel() - - if self._next_pong_check: - self._next_pong_check.cancel() - - def onPong(self, response): # noqa - """Called when pong message is received.""" - if self._last_pong_time and self.factory.debug: - log.debug("last pong was {} seconds back.".format(time.time() - self._last_pong_time)) - - self._last_pong_time = time.time() - - if self.factory.debug: - log.debug("pong => {}".format(response)) - - """ - Custom helper and exposed methods. - """ - def _loop_ping(self): # noqa - """Start a ping loop where it sends ping message every X seconds.""" - if self.factory.debug: - log.debug("ping => {}".format(self._ping_message)) - if self._last_ping_time: - log.debug("last ping was {} seconds back.".format(time.time() - self._last_ping_time)) - - # Set current time as last ping time - self._last_ping_time = time.time() - # Send a ping message to server - self.sendPing(self._ping_message) - - # Call self after X seconds - self._next_ping = self.factory.reactor.callLater(self.PING_INTERVAL, self._loop_ping) - - def _loop_pong_check(self): - """ - Timer sortof to check if connection is still there. - Checks last pong message time and disconnects the existing connection to make sure it doesn't become a ghost connection. - """ - if self._last_pong_time: - # No pong message since long time, so init reconnect - last_pong_diff = time.time() - self._last_pong_time - if last_pong_diff > (2 * self.PING_INTERVAL): - if self.factory.debug: - log.debug("Last pong was {} seconds ago. So dropping connection to reconnect.".format( - last_pong_diff)) - # drop existing connection to avoid ghost connection - self.dropConnection(abort=True) - - # Call self after X seconds - self._next_pong_check = self.factory.reactor.callLater(self.PING_INTERVAL, self._loop_pong_check) + class SmartSocketClientFactory(WebSocketClientFactory): protocol = SmartSocketClientProtocol @@ -225,9 +158,7 @@ def close(self, code=None, reason=None): self._close(code, reason) def stop(self): - """Stop the event loop. Should be used if main thread has to be closed in `on_close` method. - Reconnection mechanism cannot happen past this method - """ + """Stop the event loop. Should be used if main thread has to be closed in `on_close` method.""" #print("stop") reactor.stop() @@ -242,11 +173,11 @@ def send_request(self,token): ) #print(request) request={"task":"mw","channel":strwatchlistscrips,"token":self.feed_token,"user":self.client_code,"acctid":self.client_code} - #print(request) - #request={"task":"cn","channel":token_scripts,"token":self.feed_token,"user":self.client_code,"acctid":self.client_code} //dynamic call + self.ws.sendMessage( six.b(json.dumps(request)) ) + threading.Thread(target=self.heartBeat,daemon=True).start() #print(request) return True except Exception as e: @@ -289,6 +220,18 @@ def _on_open(self, ws): if self.on_open: return self.on_open(self) + def heartBeat(self): + while True: + try: + request={"task":"hb","channel":"","token":self.feed_token,"user":self.client_code,"acctid":self.client_code} + self.ws.sendMessage( + six.b(json.dumps(request)) + ) + + except: + print("HeartBeats Failed") + time.sleep(60) + def _parse_text_message(self, payload): """Parse text message.""" # Decode unicode data @@ -297,63 +240,63 @@ def _parse_text_message(self, payload): data =base64.b64decode(payload) - try: - data=zlib.decompress(data) - print(data.decode("utf-8")) - + data = bytes((zlib.decompress(data)).decode("utf-8"), 'utf-8') + data = json.loads(data.decode('utf8').replace("'", '"')) + data = json.loads(json.dumps(data, indent=4, sort_keys=True)) except ValueError: - return - def _parse_binary(self, bin): - #print("""Parse binary data to a (list of) ticks structure.""") - packets = self._split_packets(bin) # split data to individual ticks packet - data = [] - - for packet in packets: - instrument_token = self._unpack_int(packet, 0, 4) - segment = instrument_token & 0xff # Retrive segment constant from instrument_token - - divisor = 10000000.0 if segment == self.EXCHANGE_MAP["cds"] else 100.0 - - # All indices are not tradable - tradable = False if segment == self.EXCHANGE_MAP["indices"] else True - try: - last_trade_time = datetime.fromtimestamp(self._unpack_int(packet, 44, 48)) - except Exception: - last_trade_time = None - - try: - timestamp = datetime.fromtimestamp(self._unpack_int(packet, 60, 64)) - except Exception: - timestamp = None - - d["last_trade_time"] = last_trade_time - d["oi"] = self._unpack_int(packet, 48, 52) - d["oi_day_high"] = self._unpack_int(packet, 52, 56) - d["oi_day_low"] = self._unpack_int(packet, 56, 60) - d["timestamp"] = timestamp - - # Market depth entries. - depth = { - "buy": [], - "sell": [] - } - - # Compile the market depth lists. - for i, p in enumerate(range(64, len(packet), 12)): - depth["sell" if i >= 5 else "buy"].append({ - "quantity": self._unpack_int(packet, p, p + 4), - "price": self._unpack_int(packet, p + 4, p + 8) / divisor, - "orders": self._unpack_int(packet, p + 8, p + 10, byte_format="H") - }) - - d["depth"] = depth - - data.append(d) - - return data + self.on_ticks(self, data) + + def _parse_binary(self, bin): + #print("""Parse binary data to a (list of) ticks structure.""") + packets = self._split_packets(bin) # split data to individual ticks packet + data = [] + + for packet in packets: + instrument_token = self._unpack_int(packet, 0, 4) + segment = instrument_token & 0xff # Retrive segment constant from instrument_token + + divisor = 10000000.0 if segment == self.EXCHANGE_MAP["cds"] else 100.0 + + # All indices are not tradable + tradable = False if segment == self.EXCHANGE_MAP["indices"] else True + try: + last_trade_time = datetime.fromtimestamp(self._unpack_int(packet, 44, 48)) + except Exception: + last_trade_time = None + + try: + timestamp = datetime.fromtimestamp(self._unpack_int(packet, 60, 64)) + except Exception: + timestamp = None + + d["last_trade_time"] = last_trade_time + d["oi"] = self._unpack_int(packet, 48, 52) + d["oi_day_high"] = self._unpack_int(packet, 52, 56) + d["oi_day_low"] = self._unpack_int(packet, 56, 60) + d["timestamp"] = timestamp + + # Market depth entries. + depth = { + "buy": [], + "sell": [] + } + + # Compile the market depth lists. + for i, p in enumerate(range(64, len(packet), 12)): + depth["sell" if i >= 5 else "buy"].append({ + "quantity": self._unpack_int(packet, p, p + 4), + "price": self._unpack_int(packet, p + 4, p + 8) / divisor, + "orders": self._unpack_int(packet, p + 8, p + 10, byte_format="H") + }) + + d["depth"] = depth + + data.append(d) + + return data def _unpack_int(self, bin, start, end, byte_format="I"): """Unpack binary data as unsgined interger.""" diff --git a/setup.py b/setup.py index 7ed8684..56def31 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ setup( name="smartapi-python", - version="1.0.5.5", + version="1.0.6", author="ab-smartapi", author_email="smartapi.sdk@gmail.com", description="Angel Broking openApi integration", diff --git a/test/test.py b/test/test.py index 6cef4ec..6e84202 100644 --- a/test/test.py +++ b/test/test.py @@ -8,11 +8,15 @@ smartApi =SmartConnect(api_key="Your Api Key") login = smartApi.generateSession('Your Client Id', 'Your Password') -print(login) + refreshToken = login['data']['refreshToken'] + feedToken = smartApi.getfeedToken() + smartApi.getProfile(refreshToken) + smartApi.generateToken(refreshToken) + orderparams = { "variety": "NORMAL", "tradingsymbol": "SBIN-EQ", @@ -46,14 +50,20 @@ smartApi.cancelOrder(orderid, "NORMAL") smartApi.orderBook() + smartApi.tradeBook() + smartApi.rmsLimit() + smartApi.position() + smartApi.holding() + exchange = "NSE" tradingsymbol = "SBIN-EQ" symboltoken = 3045 smartApi.ltpData("NSE", "SBIN-EQ", "3045") + params={ "exchange": "NSE", "oldproducttype":"DELIVERY", @@ -66,20 +76,22 @@ } smartApi.convertPosition(params) + smartApi.terminateSession('Your Client Id') ## Websocket Programming from smartapi import WebSocket -FEED_TOKEN="Your Feed Token" +FEED_TOKEN=feedToken CLIENT_CODE="Your Client Id" token=None ss = WebSocket(FEED_TOKEN, CLIENT_CODE) def on_tick(ws, tick): print("Ticks: {}".format(tick)) + def on_connect(ws, response): - a=ws.send_request(token) - print("Back to Function",a) + ws.send_request(token) + def on_close(ws, code, reason): ws.stop() From 8b0f85d37040e4406d89b267b070e64c9b05d980 Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Tue, 29 Dec 2020 10:54:09 +0530 Subject: [PATCH 28/49] removed unnecessary print statements --- SmartApi/smartConnect.py | 41 ++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/SmartApi/smartConnect.py b/SmartApi/smartConnect.py index b08a3a4..b0f506a 100644 --- a/SmartApi/smartConnect.py +++ b/SmartApi/smartConnect.py @@ -145,9 +145,7 @@ def _request(self, route, method, parameters=None): params = parameters.copy() if parameters else {} uri =self._routes[route].format(**params) - print(uri) url = urljoin(self.root, uri) - print(url) hostname = socket.gethostname() clientLocalIP=socket.gethostbyname(hostname) clientPublicIP=get('https://api.ipify.org').text @@ -191,7 +189,7 @@ def _request(self, route, method, parameters=None): allow_redirects=True, timeout=self.timeout, proxies=self.proxies) - print("The Response Content",r.content) + #print("The Response Content",r.content) except Exception as e: raise e @@ -242,23 +240,26 @@ def generateSession(self,clientCode,password): params={"clientcode":clientCode,"password":password} loginResultObject=self._postRequest("api.login",params) - jwtToken=loginResultObject['data']['jwtToken'] - self.setAccessToken(jwtToken) - refreshToken=loginResultObject['data']['refreshToken'] - feedToken=loginResultObject['data']['feedToken'] - self.setRefreshToken(refreshToken) - self.setFeedToken(feedToken) - user=self.getProfile(refreshToken) - - id=user['data']['clientcode'] - #id='D88311' - self.setUserId(id) - user['data']['jwtToken']="Bearer "+jwtToken - user['data']['refreshToken']=refreshToken - print("USER",user) - return user - + if loginResultObject['status']==True or true: + jwtToken=loginResultObject['data']['jwtToken'] + self.setAccessToken(jwtToken) + refreshToken=loginResultObject['data']['refreshToken'] + feedToken=loginResultObject['data']['feedToken'] + self.setRefreshToken(refreshToken) + self.setFeedToken(feedToken) + user=self.getProfile(refreshToken) + + id=user['data']['clientcode'] + #id='D88311' + self.setUserId(id) + user['data']['jwtToken']="Bearer "+jwtToken + user['data']['refreshToken']=refreshToken + + #print("USER",user) + return user + else: + return def terminateSession(self,clientCode): logoutResponseObject=self._postRequest("api.logout",{"clientcode":clientCode}) return logoutResponseObject @@ -294,7 +295,7 @@ def renewAccessToken(self): def getProfile(self,refreshToken): user=self._getRequest("api.user.profile",{"refreshToken":refreshToken}) - print("USER PROFILE",user) + #print("USER PROFILE",user) return user def placeOrder(self,orderparams): From 15165d4cd48da76354ea15271cc6147846aa1327 Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Tue, 29 Dec 2020 10:55:25 +0530 Subject: [PATCH 29/49] removed unnecessary print statements --- SmartApi/version.py | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SmartApi/version.py b/SmartApi/version.py index 5038776..845006f 100644 --- a/SmartApi/version.py +++ b/SmartApi/version.py @@ -2,7 +2,7 @@ __description__ = "Angel Broking openApi integration" __url__ = "https://www.angelbroking.com/" __download_url__ = "https://github.com/angelbroking-github/smartapi-python" -__version__ = "1.0.6" +__version__ = "1.1.0" __author__ = "ab-smartapi" __token__ = "ab-smartapi" __author_email__ = "smartapi.sdk@gmail.com" diff --git a/setup.py b/setup.py index 56def31..1bafb88 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ setup( name="smartapi-python", - version="1.0.6", + version="1.1.0", author="ab-smartapi", author_email="smartapi.sdk@gmail.com", description="Angel Broking openApi integration", From 5e7d323583a91366a896ecc14fbfedbfda659260 Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Tue, 19 Jan 2021 10:37:37 +0530 Subject: [PATCH 30/49] Nameerror resolved --- SmartApi/smartConnect.py | 4 ++-- SmartApi/version.py | 2 +- setup.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/SmartApi/smartConnect.py b/SmartApi/smartConnect.py index b0f506a..52ee1af 100644 --- a/SmartApi/smartConnect.py +++ b/SmartApi/smartConnect.py @@ -16,7 +16,6 @@ log = logging.getLogger(__name__) - class SmartConnect(object): #_rootUrl = "https://openapisuat.angelbroking.com" _rootUrl="https://apiconnect.angelbroking.com" #prod endpoint @@ -241,7 +240,7 @@ def generateSession(self,clientCode,password): params={"clientcode":clientCode,"password":password} loginResultObject=self._postRequest("api.login",params) - if loginResultObject['status']==True or true: + if loginResultObject['status']==True : jwtToken=loginResultObject['data']['jwtToken'] self.setAccessToken(jwtToken) refreshToken=loginResultObject['data']['refreshToken'] @@ -260,6 +259,7 @@ def generateSession(self,clientCode,password): return user else: return + def terminateSession(self,clientCode): logoutResponseObject=self._postRequest("api.logout",{"clientcode":clientCode}) return logoutResponseObject diff --git a/SmartApi/version.py b/SmartApi/version.py index 845006f..b44ac8e 100644 --- a/SmartApi/version.py +++ b/SmartApi/version.py @@ -2,7 +2,7 @@ __description__ = "Angel Broking openApi integration" __url__ = "https://www.angelbroking.com/" __download_url__ = "https://github.com/angelbroking-github/smartapi-python" -__version__ = "1.1.0" +__version__ = "1.1.1" __author__ = "ab-smartapi" __token__ = "ab-smartapi" __author_email__ = "smartapi.sdk@gmail.com" diff --git a/setup.py b/setup.py index 1bafb88..98431f7 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ setup( name="smartapi-python", - version="1.1.0", + version="1.1.1", author="ab-smartapi", author_email="smartapi.sdk@gmail.com", description="Angel Broking openApi integration", From 10ed69815bdaf79e1b5cb456ec43f0528705ee7e Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Wed, 3 Mar 2021 13:21:58 +0530 Subject: [PATCH 31/49] Gtt services added --- README.md | 30 ++++- SmartApi/smartConnect.py | 147 +++++++++++++++++------- SmartApi/version.py | 2 +- SmartApi/webSocket.py | 235 ++++++++++++++++++++++++++++++++++----- setup.py | 2 +- test/test.py | 37 ++++++ 6 files changed, 384 insertions(+), 69 deletions(-) diff --git a/README.md b/README.md index df17c6f..290eb1c 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,33 @@ try: print("The order id is: {}".format(orderId)) except Exception as e: print("Order placement failed: {}".format(e.message)) - +#gtt rule creation +try: + gttCreateParams={ + "tradingsymbol" : "SBIN-EQ", + "symboltoken" : "3045", + "exchange" : "NSE", + "producttype" : "MARGIN", + "transactiontype" : "BUY", + "price" : 100000, + "qty" : 10, + "disclosedqty": 10, + "triggerprice" : 200000, + "timeperiod" : 365 + } + rule_id=gtt.gttCreateRule(gttCreateParams) + print("The GTT rule id is: {}".format(rule_id)) +except Exception as e: + print("GTT Rule creation failed: {}".format(e.message)) + +#gtt rule list +try: + status=["FORALL"] #should be a list + page=1 + count=10 + lists=smartApi.gttLists(status,page,count) +except Exception as e: + print("GTT Rule List failed: {}".format(e.message)) #logout try: logout=obj.terminateSession('Your Client Id') @@ -58,6 +84,8 @@ try: except Exception as e: print("Logout failed: {}".format(e.message)) + + ## WebSocket from smartapi import WebSocket FEED_TOKEN= "your feed token" diff --git a/SmartApi/smartConnect.py b/SmartApi/smartConnect.py index 52ee1af..cc1db99 100644 --- a/SmartApi/smartConnect.py +++ b/SmartApi/smartConnect.py @@ -11,10 +11,12 @@ from requests import get import re, uuid import socket - +import platform from smartapi.version import __version__, __title__ log = logging.getLogger(__name__) +#user_sys=platform.system() +#print("the system",user_sys) class SmartConnect(object): #_rootUrl = "https://openapisuat.angelbroking.com" @@ -81,10 +83,32 @@ class SmartConnect(object): "api.rms.limit": "/rest/secure/angelbroking/user/v1/getRMS", "api.holding": "/rest/secure/angelbroking/portfolio/v1/getHolding", "api.position": "/rest/secure/angelbroking/order/v1/getPosition", - "api.convert.position": "/rest/secure/angelbroking/order/v1/convertPosition" + "api.convert.position": "/rest/secure/angelbroking/order/v1/convertPosition", + + "api.gtt.create":"/gtt-service/rest/secure/angelbroking/gtt/v1/createRule", + "api.gtt.modify":"/gtt-service/rest/secure/angelbroking/gtt/v1/modifyRule", + "api.gtt.cancel":"/gtt-service/rest/secure/angelbroking/gtt/v1/cancelRule", + "api.gtt.details":"/rest/secure/angelbroking/gtt/v1/ruleDetails", + "api.gtt.list":"/rest/secure/angelbroking/gtt/v1/ruleList" } - def __init__(self, api_key=None, access_token=None, refresh_token=None,feed_token=None, userId=None, root=None, debug=False, timeout=None, proxies=None, pool=None, disable_ssl=False): + + try: + clientPublicIp= get('https://api.ipify.org').text + hostname = socket.gethostname() + clientLocalIp=socket.gethostbyname(hostname) + except Exception as e: + print("Exception while retriving IP Address,using local host IP address",e) + finally: + clientPublicIp="106.193.147.98" + clientLocalIp="127.0.0.1" + clientMacAddress=':'.join(re.findall('..', '%012x' % uuid.getnode())) + accept = "application/json" + userType = "USER" + sourceID = "WEB" + + + def __init__(self, api_key=None, access_token=None, refresh_token=None,feed_token=None, userId=None, root=None, debug=False, timeout=None, proxies=None, pool=None, disable_ssl=False,accept=None,userType=None,sourceID=None,Authorization=None,clientPublicIP=None,clientMacAddress=None,clientLocalIP=None,privateKey=None): self.debug = debug self.api_key = api_key self.session_expiry_hook = None @@ -96,6 +120,14 @@ def __init__(self, api_key=None, access_token=None, refresh_token=None,feed_toke self.proxies = proxies if proxies else {} self.root = root or self._rootUrl self.timeout = timeout or self._default_timeout + self.Authorization= None + self.clientLocalIP=self.clientLocalIp + self.clientPublicIP=self.clientPublicIp + self.clientMacAddress=self.clientMacAddress + self.privateKey=api_key + self.accept=self.accept + self.userType=self.userType + self.sourceID=self.sourceID if pool: self.reqsession = requests.Session() @@ -107,6 +139,17 @@ def __init__(self, api_key=None, access_token=None, refresh_token=None,feed_toke # disable requests SSL warning requests.packages.urllib3.disable_warnings() + def requestHeaders(self): + return{ + "Content-type":self.accept, + "X-ClientLocalIP": self.clientLocalIp, + "X-ClientPublicIP": self.clientPublicIp, + "X-MACAddress": self.clientMacAddress, + "Accept": self.accept, + "X-PrivateKey": self.privateKey, + "X-UserType": self.userType, + "X-SourceID": self.sourceID + } def setSessionExpiryHook(self, method): if not callable(method): @@ -145,30 +188,11 @@ def _request(self, route, method, parameters=None): uri =self._routes[route].format(**params) url = urljoin(self.root, uri) - hostname = socket.gethostname() - clientLocalIP=socket.gethostbyname(hostname) - clientPublicIP=get('https://api.ipify.org').text - macAddress = ':'.join(re.findall('..', '%012x' % uuid.getnode())) - privateKey = self.api_key - accept = "application/json" - userType = "USER" - sourceID = "WEB" + # Custom headers - headers = { - #"X-SmartApi-Version": "", - #"User-Agent": self._user_agent() - "Content-type":accept, - "X-ClientLocalIP": clientLocalIP, - "X-ClientPublicIP": clientPublicIP, - "X-MACAddress": macAddress, - "Accept": accept, - "X-PrivateKey": privateKey, - "X-UserType": userType, - "X-SourceID": sourceID - } + headers = self.requestHeaders() - #if self.api_key and self.access_token: if self.access_token: # set authorization header @@ -188,7 +212,7 @@ def _request(self, route, method, parameters=None): allow_redirects=True, timeout=self.timeout, proxies=self.proxies) - #print("The Response Content",r.content) + except Exception as e: raise e @@ -239,8 +263,8 @@ def generateSession(self,clientCode,password): params={"clientcode":clientCode,"password":password} loginResultObject=self._postRequest("api.login",params) - - if loginResultObject['status']==True : + + if loginResultObject['status']==True: jwtToken=loginResultObject['data']['jwtToken'] self.setAccessToken(jwtToken) refreshToken=loginResultObject['data']['refreshToken'] @@ -255,11 +279,10 @@ def generateSession(self,clientCode,password): user['data']['jwtToken']="Bearer "+jwtToken user['data']['refreshToken']=refreshToken - #print("USER",user) + return user else: - return - + return loginResultObject def terminateSession(self,clientCode): logoutResponseObject=self._postRequest("api.logout",{"clientcode":clientCode}) return logoutResponseObject @@ -274,14 +297,10 @@ def generateToken(self,refresh_token): return response def renewAccessToken(self): - - # h = hashlib.sha256(self.api_key.encode("utf-8") + refresh_token.encode("utf-8") + access_token.encode("utf-8")) - # checksum = h.hexdigest() - response =self._postRequest('api.refresh', { "jwtToken": self.access_token, "refreshToken": self.refresh_token, - #"checksum": checksum + }) tokenSet={} @@ -295,11 +314,10 @@ def renewAccessToken(self): def getProfile(self,refreshToken): user=self._getRequest("api.user.profile",{"refreshToken":refreshToken}) - #print("USER PROFILE",user) return user def placeOrder(self,orderparams): - #params = {"exchange":orderparams.exchange,"symbolToken":orderparams.symboltoken,"transactionType":orderparams.transactionType,"quantity":orderparams.quantity,"price":orderparams.price,"productType":orderparams.producttype,"orderType":orderparams.ordertype,"duration":orderparams.duration,"variety":orderparams.variety,"tradingSymbol":orderparams.tradingsymbol,"triggerPrice":orderparams.trigger_price,"squareoff":orderparams.squareoff,"stoploss":orderparams.stoploss,"trailingStoploss":orderparams.trailing_stoploss,"tag":orderparams.tag} + params=orderparams for k in list(params.keys()): @@ -307,7 +325,7 @@ def placeOrder(self,orderparams): del(params[k]) orderResponse= self._postRequest("api.order.place", params)['data']['orderid'] - + return orderResponse def modifyOrder(self,orderparams): @@ -318,8 +336,6 @@ def modifyOrder(self,orderparams): del(params[k]) orderResponse= self._postRequest("api.order.modify", params) - #order=Order(orderResponse) - #order['orderId']=orderResponse['data']['orderid'] return orderResponse def cancelOrder(self, order_id,variety): @@ -365,6 +381,57 @@ def convertPosition(self,positionParams): return convertPositionResponse + def gttCreateRule(self,createRuleParams): + params=createRuleParams + for k in list(params.keys()): + if params[k] is None: + del(params[k]) + + createGttRuleResponse=self._postRequest("api.gtt.create",params) + print(createGttRuleResponse) + return createGttRuleResponse['data']['id'] + + def gttModifyRule(self,modifyRuleParams): + params=modifyRuleParams + for k in list(params.keys()): + if params[k] is None: + del(params[k]) + modifyGttRuleResponse=self._postRequest("api.gtt.modify",params) + print(modifyGttRuleResponse) + return modifyGttRuleResponse['data']['id'] + + def gttCancelRule(self,gttCancelParams): + params=gttCancelParams + for k in list(params.keys()): + if params[k] is None: + del(params[k]) + + print(params) + cancelGttRuleResponse=self._postRequest("api.gtt.cancel",params) + print(cancelGttRuleResponse) + return cancelGttRuleResponse + + def gttDetails(self,id): + params={ + "id":id + } + gttDetailsResponse=self._postRequest("api.gtt.details",params) + return gttDetailsResponse + + def gttLists(self,status,page,count): + if type(status)== list: + params={ + "status":status, + "page":page, + "count":count + } + gttListResponse=self._postRequest("api.gtt.list",params) + print(gttListResponse) + return gttListResponse + else: + message="The status param is entered as" +str(type(status))+". Please enter status param as a list i.e., status=['CANCELLED']" + return message + def _user_agent(self): return (__title__ + "-python/").capitalize() + __version__ diff --git a/SmartApi/version.py b/SmartApi/version.py index b44ac8e..817b16a 100644 --- a/SmartApi/version.py +++ b/SmartApi/version.py @@ -2,7 +2,7 @@ __description__ = "Angel Broking openApi integration" __url__ = "https://www.angelbroking.com/" __download_url__ = "https://github.com/angelbroking-github/smartapi-python" -__version__ = "1.1.1" +__version__ = "1.2.0" __author__ = "ab-smartapi" __token__ = "ab-smartapi" __author_email__ = "smartapi.sdk@gmail.com" diff --git a/SmartApi/webSocket.py b/SmartApi/webSocket.py index adc9aff..7d93035 100644 --- a/SmartApi/webSocket.py +++ b/SmartApi/webSocket.py @@ -11,12 +11,21 @@ from datetime import datetime from twisted.internet import reactor, ssl from twisted.python import log as twisted_log +from twisted.internet.protocol import ReconnectingClientFactory from autobahn.twisted.websocket import WebSocketClientProtocol, \ WebSocketClientFactory, connectWS log = logging.getLogger(__name__) class SmartSocketClientProtocol(WebSocketClientProtocol): + PING_INTERVAL = 2.5 + KEEPALIVE_INTERVAL = 5 + + _ping_message = "" + _next_ping = None + _next_pong_check = None + _last_pong_time = None + _last_ping_time = None def __init__(self, *args, **kwargs): super(SmartSocketClientProtocol,self).__init__(*args,**kwargs) @@ -29,6 +38,11 @@ def onConnect(self, response): # noqa self.factory.on_connect(self, response) def onOpen(self): + # send ping + self._loop_ping() + # init last pong check after X seconds + self._loop_pong_check() + if self.factory.on_open: self.factory.on_open(self) @@ -48,9 +62,70 @@ def onClose(self, was_clean, code, reason): # noqa if self.factory.on_close: self.factory.on_close(self, code, reason) - -class SmartSocketClientFactory(WebSocketClientFactory): + + # Cancel next ping and timer + self._last_ping_time = None + self._last_pong_time = None + + if self._next_ping: + self._next_ping.cancel() + + if self._next_pong_check: + self._next_pong_check.cancel() + + def onPong(self, response): # noqa + """Called when pong message is received.""" + if self._last_pong_time and self.factory.debug: + log.debug("last pong was {} seconds back.".format(time.time() - self._last_pong_time)) + + self._last_pong_time = time.time() + + if self.factory.debug: + log.debug("pong => {}".format(response)) + + """ + Custom helper and exposed methods. + """ + def _loop_ping(self): # noqa + """Start a ping loop where it sends ping message every X seconds.""" + if self.factory.debug: + log.debug("ping => {}".format(self._ping_message)) + if self._last_ping_time: + log.debug("last ping was {} seconds back.".format(time.time() - self._last_ping_time)) + + # Set current time as last ping time + self._last_ping_time = time.time() + # Send a ping message to server + self.sendPing(self._ping_message) + + # Call self after X seconds + self._next_ping = self.factory.reactor.callLater(self.PING_INTERVAL, self._loop_ping) + + def _loop_pong_check(self): + """ + Timer sortof to check if connection is still there. + Checks last pong message time and disconnects the existing connection to make sure it doesn't become a ghost connection. + """ + if self._last_pong_time: + # No pong message since long time, so init reconnect + last_pong_diff = time.time() - self._last_pong_time + if last_pong_diff > (2 * self.PING_INTERVAL): + if self.factory.debug: + log.debug("Last pong was {} seconds ago. So dropping connection to reconnect.".format( + last_pong_diff)) + # drop existing connection to avoid ghost connection + self.dropConnection(abort=True) + + # Call self after X seconds + self._next_pong_check = self.factory.reactor.callLater(self.PING_INTERVAL, self._loop_pong_check) + +class SmartSocketClientFactory(WebSocketClientFactory,ReconnectingClientFactory): protocol = SmartSocketClientProtocol + + maxDelay = 5 + maxRetries = 10 + + _last_connection_time = None def __init__(self, *args, **kwargs): """Initialize with default callback method values.""" @@ -61,10 +136,52 @@ def __init__(self, *args, **kwargs): self.on_close = None self.on_message = None self.on_connect = None + self.on_reconnect = None + self.on_noreconnect = None super(SmartSocketClientFactory, self).__init__(*args, **kwargs) + def startedConnecting(self, connector): # noqa + """On connecting start or reconnection.""" + if not self._last_connection_time and self.debug: + log.debug("Start WebSocket connection.") + + self._last_connection_time = time.time() + + def clientConnectionFailed(self, connector, reason): # noqa + """On connection failure (When connect request fails)""" + if self.retries > 0: + log.error("Retrying connection. Retry attempt count: {}. Next retry in around: {} seconds".format(self.retries, int(round(self.delay)))) + + # on reconnect callback + if self.on_reconnect: + self.on_reconnect(self.retries) + + # Retry the connection + self.retry(connector) + self.send_noreconnect() + + def clientConnectionLost(self, connector, reason): # noqa + """On connection lost (When ongoing connection got disconnected).""" + if self.retries > 0: + # on reconnect callback + if self.on_reconnect: + self.on_reconnect(self.retries) + + # Retry the connection + self.retry(connector) + self.send_noreconnect() + + def send_noreconnect(self): + """Callback `no_reconnect` if max retries are exhausted.""" + if self.maxRetries is not None and (self.retries > self.maxRetries): + if self.debug: + log.debug("Maximum retries ({}) exhausted.".format(self.maxRetries)) + + if self.on_noreconnect: + self.on_noreconnect() + class WebSocket(object): EXCHANGE_MAP = { @@ -78,15 +195,50 @@ class WebSocket(object): "mcxsx": 8, "indices": 9 } + + # Default connection timeout + CONNECT_TIMEOUT = 30 + # Default Reconnect max delay. + RECONNECT_MAX_DELAY = 60 + # Default reconnect attempts + RECONNECT_MAX_TRIES = 50 + ROOT_URI='wss://omnefeeds.angelbroking.com/NestHtml5Mobile/socket/stream' + + # Flag to set if its first connect + _is_first_connect = True + + # Minimum delay which should be set between retries. User can't set less than this + _minimum_reconnect_max_delay = 5 + # Maximum number or retries user can set + _maximum_reconnect_max_tries = 300 feed_token=None client_code=None - def __init__(self, FEED_TOKEN, CLIENT_CODE, debug=False, root=None): + def __init__(self, FEED_TOKEN, CLIENT_CODE,task,debug=False, root=None,reconnect=True, reconnect_max_tries=RECONNECT_MAX_TRIES, reconnect_max_delay=RECONNECT_MAX_DELAY,connect_timeout=CONNECT_TIMEOUT): + + self.root = root or self.ROOT_URI self.feed_token= FEED_TOKEN self.client_code= CLIENT_CODE + self.task=task - + # Set max reconnect tries + if reconnect_max_tries > self._maximum_reconnect_max_tries: + log.warning("`reconnect_max_tries` can not be more than {val}. Setting to highest possible value - {val}.".format( + val=self._maximum_reconnect_max_tries)) + self.reconnect_max_tries = self._maximum_reconnect_max_tries + else: + self.reconnect_max_tries = reconnect_max_tries + + # Set max reconnect delay + if reconnect_max_delay < self._minimum_reconnect_max_delay: + log.warning("`reconnect_max_delay` can not be less than {val}. Setting to lowest possible value - {val}.".format( + val=self._minimum_reconnect_max_delay)) + self.reconnect_max_delay = self._minimum_reconnect_max_delay + else: + self.reconnect_max_delay = reconnect_max_delay + + self.connect_timeout = connect_timeout # Debug enables logs self.debug = debug @@ -97,6 +249,8 @@ def __init__(self, FEED_TOKEN, CLIENT_CODE, debug=False, root=None): self.on_error = None self.on_connect = None self.on_message = None + self.on_reconnect = None + self.on_noreconnect = None def _create_connection(self, url, **kwargs): """Create a WebSocket client connection.""" @@ -113,6 +267,12 @@ def _create_connection(self, url, **kwargs): self.factory.on_close = self._on_close self.factory.on_message = self._on_message self.factory.on_connect = self._on_connect + self.factory.on_reconnect = self._on_reconnect + self.factory.on_noreconnect = self._on_noreconnect + + + self.factory.maxDelay = self.reconnect_max_delay + self.factory.maxRetries = self.reconnect_max_tries def connect(self, threaded=False, disable_ssl_verification=False, proxy=None): @@ -155,35 +315,45 @@ def _close(self, code=None, reason=None): def close(self, code=None, reason=None): """Close the WebSocket connection.""" + self.stop_retry() self._close(code, reason) def stop(self): """Stop the event loop. Should be used if main thread has to be closed in `on_close` method.""" #print("stop") + reactor.stop() + def stop_retry(self): + """Stop auto retry when it is in progress.""" + if self.factory: + self.factory.stopTrying() + def send_request(self,token): - strwatchlistscrips = token #dynamic call - - try: - #print("Inside") - request={"task":"cn","channel":"","token":self.feed_token,"user":self.client_code,"acctid":self.client_code} - self.ws.sendMessage( - six.b(json.dumps(request)) - ) - #print(request) - request={"task":"mw","channel":strwatchlistscrips,"token":self.feed_token,"user":self.client_code,"acctid":self.client_code} + if self.task in ("mw","sfi","dp"): + strwatchlistscrips = token #dynamic call - self.ws.sendMessage( - six.b(json.dumps(request)) - ) - threading.Thread(target=self.heartBeat,daemon=True).start() - #print(request) - return True - except Exception as e: - self._close(reason="Error while request sending: {}".format(str(e))) - raise - + try: + #print("Inside") + request={"task":"cn","channel":"","token":self.feed_token,"user":self.client_code,"acctid":self.client_code} + self.ws.sendMessage( + six.b(json.dumps(request)) + ) + #print(request) + request={"task":self.task,"channel":strwatchlistscrips,"token":self.feed_token,"user":self.client_code,"acctid":self.client_code} + + self.ws.sendMessage( + six.b(json.dumps(request)) + ) + threading.Thread(target=self.heartBeat,daemon=True).start() + #print(request) + return True + except Exception as e: + self._close(reason="Error while request sending: {}".format(str(e))) + raise + else: + print("The task entered is invalid, Please enter correct task(mw,sfi,dp) ") + def _on_connect(self, ws, response): self.ws = ws if self.on_connect: @@ -217,9 +387,23 @@ def _on_message(self, ws, payload, is_binary): self._parse_text_message(payload) def _on_open(self, ws): + + if not self._is_first_connect: + self.connect() + + self._is_first_connect = False + if self.on_open: return self.on_open(self) + def _on_reconnect(self, attempts_count): + if self.on_reconnect: + return self.on_reconnect(self, attempts_count) + + def _on_noreconnect(self): + if self.on_noreconnect: + return self.on_noreconnect(self) + def heartBeat(self): while True: try: @@ -318,5 +502,4 @@ def _split_packets(self, bin): j = j + 2 + packet_length return packets - - + \ No newline at end of file diff --git a/setup.py b/setup.py index 98431f7..827dd5a 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ setup( name="smartapi-python", - version="1.1.1", + version="1.2.0", author="ab-smartapi", author_email="smartapi.sdk@gmail.com", description="Angel Broking openApi integration", diff --git a/test/test.py b/test/test.py index 6e84202..3d9b596 100644 --- a/test/test.py +++ b/test/test.py @@ -76,6 +76,43 @@ } smartApi.convertPosition(params) +gttCreateParams={ + "tradingsymbol" : "SBIN-EQ", + "symboltoken" : "3045", + "exchange" : "NSE", + "producttype" : "MARGIN", + "transactiontype" : "BUY", + "price" : 100000, + "qty" : 10, + "disclosedqty": 10, + "triggerprice" : 200000, + "timeperiod" : 365 + } +rule_id=smartApi.gttCreateRule(gttCreateParams) + +gttModifyParams={ + "id": rule_id, + "symboltoken":"3045", + "exchange":"NSE", + "price":19500, + "quantity":10, + "triggerprice":200000, + "disclosedqty":10, + "timeperiod":365 + } +modified_id=smartApi.gttModifyRule(gttModifyParams) + +cancelParams={ + "id": rule_id, + "symboltoken":"3045", + "exchange":"NSE" + } + +cancelled_id=smartApi.gttCancelRule(cancelParams) + +smartApi.gttDetails(rule_id) + +smartApi.gttLists('List of status',,) smartApi.terminateSession('Your Client Id') From c361cd8fd8804bc92b1372c9c809dcb3eb0eacaf Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Mon, 8 Mar 2021 11:08:44 +0530 Subject: [PATCH 32/49] Condition added for Public Ip Header --- SmartApi/smartConnect.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/SmartApi/smartConnect.py b/SmartApi/smartConnect.py index cc1db99..40fbf3e 100644 --- a/SmartApi/smartConnect.py +++ b/SmartApi/smartConnect.py @@ -94,7 +94,9 @@ class SmartConnect(object): try: - clientPublicIp= get('https://api.ipify.org').text + clientPublicIp= " " + get('https://api.ipify.org').text + if " " in clientPublicIp: + clientPublicIp=clientPublicIp.replace(" ","") hostname = socket.gethostname() clientLocalIp=socket.gethostbyname(hostname) except Exception as e: From 28ee960c866635eaab2b6c1dabd61b04cc991bc5 Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Mon, 8 Mar 2021 15:47:13 +0530 Subject: [PATCH 33/49] Changes in websocket-sendRequest(token,task) --- README.md | 4 ++-- SmartApi/version.py | 2 +- SmartApi/webSocket.py | 10 +++++----- setup.py | 2 +- test/test.py | 3 ++- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 290eb1c..c5111e1 100644 --- a/README.md +++ b/README.md @@ -91,14 +91,14 @@ from smartapi import WebSocket FEED_TOKEN= "your feed token" CLIENT_CODE="your client Id" token="channel you want the information of" #"nse_cm|2885&nse_cm|1594&nse_cm|11536" - +task="task" #'mw'|'sfi'|'dp' ss = WebSocket(FEED_TOKEN, CLIENT_CODE) def on_tick(ws, tick): print("Ticks: {}".format(tick)) def on_connect(ws, response): - ws.send_request(token) + ws.send_request(token,task) def on_close(ws, code, reason): ws.stop() diff --git a/SmartApi/version.py b/SmartApi/version.py index 817b16a..457ec5c 100644 --- a/SmartApi/version.py +++ b/SmartApi/version.py @@ -2,7 +2,7 @@ __description__ = "Angel Broking openApi integration" __url__ = "https://www.angelbroking.com/" __download_url__ = "https://github.com/angelbroking-github/smartapi-python" -__version__ = "1.2.0" +__version__ = "1.2.2" __author__ = "ab-smartapi" __token__ = "ab-smartapi" __author_email__ = "smartapi.sdk@gmail.com" diff --git a/SmartApi/webSocket.py b/SmartApi/webSocket.py index 7d93035..18778ec 100644 --- a/SmartApi/webSocket.py +++ b/SmartApi/webSocket.py @@ -214,13 +214,13 @@ class WebSocket(object): _maximum_reconnect_max_tries = 300 feed_token=None client_code=None - def __init__(self, FEED_TOKEN, CLIENT_CODE,task,debug=False, root=None,reconnect=True, reconnect_max_tries=RECONNECT_MAX_TRIES, reconnect_max_delay=RECONNECT_MAX_DELAY,connect_timeout=CONNECT_TIMEOUT): + def __init__(self, FEED_TOKEN, CLIENT_CODE,debug=False, root=None,reconnect=True,reconnect_max_tries=RECONNECT_MAX_TRIES, reconnect_max_delay=RECONNECT_MAX_DELAY,connect_timeout=CONNECT_TIMEOUT): self.root = root or self.ROOT_URI self.feed_token= FEED_TOKEN self.client_code= CLIENT_CODE - self.task=task + # Set max reconnect tries if reconnect_max_tries > self._maximum_reconnect_max_tries: @@ -329,8 +329,8 @@ def stop_retry(self): if self.factory: self.factory.stopTrying() - def send_request(self,token): - if self.task in ("mw","sfi","dp"): + def send_request(self,token,task): + if task in ("mw","sfi","dp"): strwatchlistscrips = token #dynamic call try: @@ -340,7 +340,7 @@ def send_request(self,token): six.b(json.dumps(request)) ) #print(request) - request={"task":self.task,"channel":strwatchlistscrips,"token":self.feed_token,"user":self.client_code,"acctid":self.client_code} + request={"task":task,"channel":strwatchlistscrips,"token":self.feed_token,"user":self.client_code,"acctid":self.client_code} self.ws.sendMessage( six.b(json.dumps(request)) diff --git a/setup.py b/setup.py index 827dd5a..e6d0d5a 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ setup( name="smartapi-python", - version="1.2.0", + version="1.2.2", author="ab-smartapi", author_email="smartapi.sdk@gmail.com", description="Angel Broking openApi integration", diff --git a/test/test.py b/test/test.py index 3d9b596..2f6f8c1 100644 --- a/test/test.py +++ b/test/test.py @@ -122,12 +122,13 @@ FEED_TOKEN=feedToken CLIENT_CODE="Your Client Id" token=None +task=None ss = WebSocket(FEED_TOKEN, CLIENT_CODE) def on_tick(ws, tick): print("Ticks: {}".format(tick)) def on_connect(ws, response): - ws.send_request(token) + ws.send_request(token,task) def on_close(ws, code, reason): ws.stop() From 0fdd1b94bb9187c051fce5b7f53c8d8e070d0e42 Mon Sep 17 00:00:00 2001 From: abhijeetbote Date: Fri, 26 Mar 2021 11:14:21 +0530 Subject: [PATCH 34/49] Historic api added and Websocket Open Forum Issues Resolved --- README.md | 20 +++++- SmartApi/smartConnect.py | 65 +++++------------- SmartApi/version.py | 2 +- SmartApi/webSocket.py | 143 ++++++++++++--------------------------- setup.py | 2 +- 5 files changed, 79 insertions(+), 153 deletions(-) diff --git a/README.md b/README.md index 290eb1c..601923a 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,19 @@ try: lists=smartApi.gttLists(status,page,count) except Exception as e: print("GTT Rule List failed: {}".format(e.message)) + +#Historic api +try: + historicParam={ + "exchange": "NSE", + "symboltoken": "3045", + "interval": "MINUTE", + "fromdate": "2021-02-08 09:00", + "todate": "2021-02-08 09:16" + } + smartApi.getCandleData(historicParam) +except Exception as e: + print("Historic Api failed: {}".format(e.message)) #logout try: logout=obj.terminateSession('Your Client Id') @@ -91,15 +104,16 @@ from smartapi import WebSocket FEED_TOKEN= "your feed token" CLIENT_CODE="your client Id" token="channel you want the information of" #"nse_cm|2885&nse_cm|1594&nse_cm|11536" - +task="task" #"mw"|"sfi"|"dp" ss = WebSocket(FEED_TOKEN, CLIENT_CODE) def on_tick(ws, tick): print("Ticks: {}".format(tick)) def on_connect(ws, response): - ws.send_request(token) - + ws.websocket_connection() # Websocket connection + ws.send_request(token,task) + def on_close(ws, code, reason): ws.stop() diff --git a/SmartApi/smartConnect.py b/SmartApi/smartConnect.py index 40fbf3e..c8f65a8 100644 --- a/SmartApi/smartConnect.py +++ b/SmartApi/smartConnect.py @@ -24,47 +24,6 @@ class SmartConnect(object): #_login_url ="https://smartapi.angelbroking.com/login" _login_url="https://smartapi.angelbroking.com/publisher-login" #prod endpoint _default_timeout = 7 # In seconds - # Products - PRODUCT_MIS = "MIS" - - PRODUCT_CNC = "CNC" - PRODUCT_NRML = "NRML" - PRODUCT_CO = "CO" - PRODUCT_BO = "BO" - - # Order types - ORDER_TYPE_MARKET = "MARKET" - ORDER_TYPE_LIMIT = "LIMIT" - ORDER_TYPE_SLM = "SL-M" - ORDER_TYPE_SL = "SL" - - # Varities - VARIETY_REGULAR = "regular" - VARIETY_BO = "bo" - VARIETY_CO = "co" - VARIETY_AMO = "amo" - - # Transaction type - TRANSACTION_TYPE_BUY = "BUY" - TRANSACTION_TYPE_SELL = "SELL" - - # Validity - VALIDITY_DAY = "DAY" - VALIDITY_IOC = "IOC" - - # Exchanges - EXCHANGE_NSE = "NSE" - EXCHANGE_BSE = "BSE" - EXCHANGE_NFO = "NFO" - EXCHANGE_CDS = "CDS" - EXCHANGE_BFO = "BFO" - EXCHANGE_MCX = "MCX" - EXCHANGE_NCDEX="NCDEX" - - # Status constants - STATUS_COMPLETE = "COMPLETE" - STATUS_REJECTED = "REJECTED" - STATUS_CANCELLED = "CANCELLED" _routes = { "api.login":"/rest/auth/angelbroking/user/v1/loginByPassword", @@ -89,7 +48,9 @@ class SmartConnect(object): "api.gtt.modify":"/gtt-service/rest/secure/angelbroking/gtt/v1/modifyRule", "api.gtt.cancel":"/gtt-service/rest/secure/angelbroking/gtt/v1/cancelRule", "api.gtt.details":"/rest/secure/angelbroking/gtt/v1/ruleDetails", - "api.gtt.list":"/rest/secure/angelbroking/gtt/v1/ruleList" + "api.gtt.list":"/rest/secure/angelbroking/gtt/v1/ruleList", + + "api.candle.data":"/rest/secure/angelbroking/historical/v1/getCandleData" } @@ -159,7 +120,7 @@ def setSessionExpiryHook(self, method): self.session_expiry_hook = method def getUserId(): - return userId; + return userId def setUserId(self,id): self.userId=id @@ -390,7 +351,7 @@ def gttCreateRule(self,createRuleParams): del(params[k]) createGttRuleResponse=self._postRequest("api.gtt.create",params) - print(createGttRuleResponse) + #print(createGttRuleResponse) return createGttRuleResponse['data']['id'] def gttModifyRule(self,modifyRuleParams): @@ -399,7 +360,7 @@ def gttModifyRule(self,modifyRuleParams): if params[k] is None: del(params[k]) modifyGttRuleResponse=self._postRequest("api.gtt.modify",params) - print(modifyGttRuleResponse) + #print(modifyGttRuleResponse) return modifyGttRuleResponse['data']['id'] def gttCancelRule(self,gttCancelParams): @@ -408,9 +369,9 @@ def gttCancelRule(self,gttCancelParams): if params[k] is None: del(params[k]) - print(params) + #print(params) cancelGttRuleResponse=self._postRequest("api.gtt.cancel",params) - print(cancelGttRuleResponse) + #print(cancelGttRuleResponse) return cancelGttRuleResponse def gttDetails(self,id): @@ -428,12 +389,20 @@ def gttLists(self,status,page,count): "count":count } gttListResponse=self._postRequest("api.gtt.list",params) - print(gttListResponse) + #print(gttListResponse) return gttListResponse else: message="The status param is entered as" +str(type(status))+". Please enter status param as a list i.e., status=['CANCELLED']" return message + def getCandleData(self,historicDataParams): + params=historicDataParams + for k in list(params.keys()): + if params[k] is None: + del(params[k]) + getCandleDataResponse=self._postRequest("api.candle.data",historicDataParams) + return getCandleDataResponse + def _user_agent(self): return (__title__ + "-python/").capitalize() + __version__ diff --git a/SmartApi/version.py b/SmartApi/version.py index 817b16a..40c5528 100644 --- a/SmartApi/version.py +++ b/SmartApi/version.py @@ -2,7 +2,7 @@ __description__ = "Angel Broking openApi integration" __url__ = "https://www.angelbroking.com/" __download_url__ = "https://github.com/angelbroking-github/smartapi-python" -__version__ = "1.2.0" +__version__ = "1.2.3" __author__ = "ab-smartapi" __token__ = "ab-smartapi" __author_email__ = "smartapi.sdk@gmail.com" diff --git a/SmartApi/webSocket.py b/SmartApi/webSocket.py index 7d93035..2538d97 100644 --- a/SmartApi/webSocket.py +++ b/SmartApi/webSocket.py @@ -18,14 +18,6 @@ log = logging.getLogger(__name__) class SmartSocketClientProtocol(WebSocketClientProtocol): - PING_INTERVAL = 2.5 - KEEPALIVE_INTERVAL = 5 - - _ping_message = "" - _next_ping = None - _next_pong_check = None - _last_pong_time = None - _last_ping_time = None def __init__(self, *args, **kwargs): super(SmartSocketClientProtocol,self).__init__(*args,**kwargs) @@ -38,17 +30,13 @@ def onConnect(self, response): # noqa self.factory.on_connect(self, response) def onOpen(self): - # send ping - self._loop_ping() - # init last pong check after X seconds - self._loop_pong_check() - if self.factory.on_open: self.factory.on_open(self) + def onMessage(self, payload, is_binary): # noqa - #print("""Called when text or binary message is received.""",payload,is_binary) + """Called when text or binary message is received.""" if self.factory.on_message: self.factory.on_message(self, payload, is_binary) @@ -63,65 +51,9 @@ def onClose(self, was_clean, code, reason): # noqa self.factory.on_close(self, code, reason) - # Cancel next ping and timer - self._last_ping_time = None - self._last_pong_time = None - - if self._next_ping: - self._next_ping.cancel() - - if self._next_pong_check: - self._next_pong_check.cancel() - - def onPong(self, response): # noqa - """Called when pong message is received.""" - if self._last_pong_time and self.factory.debug: - log.debug("last pong was {} seconds back.".format(time.time() - self._last_pong_time)) - - self._last_pong_time = time.time() - - if self.factory.debug: - log.debug("pong => {}".format(response)) - - """ - Custom helper and exposed methods. - """ - def _loop_ping(self): # noqa - """Start a ping loop where it sends ping message every X seconds.""" - if self.factory.debug: - log.debug("ping => {}".format(self._ping_message)) - if self._last_ping_time: - log.debug("last ping was {} seconds back.".format(time.time() - self._last_ping_time)) - - # Set current time as last ping time - self._last_ping_time = time.time() - # Send a ping message to server - self.sendPing(self._ping_message) - - # Call self after X seconds - self._next_ping = self.factory.reactor.callLater(self.PING_INTERVAL, self._loop_ping) - - def _loop_pong_check(self): - """ - Timer sortof to check if connection is still there. - Checks last pong message time and disconnects the existing connection to make sure it doesn't become a ghost connection. - """ - if self._last_pong_time: - # No pong message since long time, so init reconnect - last_pong_diff = time.time() - self._last_pong_time - if last_pong_diff > (2 * self.PING_INTERVAL): - if self.factory.debug: - log.debug("Last pong was {} seconds ago. So dropping connection to reconnect.".format( - last_pong_diff)) - # drop existing connection to avoid ghost connection - self.dropConnection(abort=True) - - # Call self after X seconds - self._next_pong_check = self.factory.reactor.callLater(self.PING_INTERVAL, self._loop_pong_check) - class SmartSocketClientFactory(WebSocketClientFactory,ReconnectingClientFactory): protocol = SmartSocketClientProtocol - + maxDelay = 5 maxRetries = 10 @@ -152,7 +84,7 @@ def startedConnecting(self, connector): # noqa def clientConnectionFailed(self, connector, reason): # noqa """On connection failure (When connect request fails)""" if self.retries > 0: - log.error("Retrying connection. Retry attempt count: {}. Next retry in around: {} seconds".format(self.retries, int(round(self.delay)))) + print("Retrying connection. Retry attempt count: {}. Next retry in around: {} seconds".format(self.retries, int(round(self.delay)))) # on reconnect callback if self.on_reconnect: @@ -182,7 +114,6 @@ def send_noreconnect(self): if self.on_noreconnect: self.on_noreconnect() - class WebSocket(object): EXCHANGE_MAP = { "nse": 1, @@ -195,7 +126,6 @@ class WebSocket(object): "mcxsx": 8, "indices": 9 } - # Default connection timeout CONNECT_TIMEOUT = 30 # Default Reconnect max delay. @@ -212,16 +142,16 @@ class WebSocket(object): _minimum_reconnect_max_delay = 5 # Maximum number or retries user can set _maximum_reconnect_max_tries = 300 + feed_token=None client_code=None - def __init__(self, FEED_TOKEN, CLIENT_CODE,task,debug=False, root=None,reconnect=True, reconnect_max_tries=RECONNECT_MAX_TRIES, reconnect_max_delay=RECONNECT_MAX_DELAY,connect_timeout=CONNECT_TIMEOUT): + def __init__(self, FEED_TOKEN, CLIENT_CODE,debug=False, root=None,reconnect=True,reconnect_max_tries=RECONNECT_MAX_TRIES, reconnect_max_delay=RECONNECT_MAX_DELAY,connect_timeout=CONNECT_TIMEOUT): self.root = root or self.ROOT_URI self.feed_token= FEED_TOKEN self.client_code= CLIENT_CODE - self.task=task - + # Set max reconnect tries if reconnect_max_tries > self._maximum_reconnect_max_tries: log.warning("`reconnect_max_tries` can not be more than {val}. Setting to highest possible value - {val}.".format( @@ -238,7 +168,8 @@ def __init__(self, FEED_TOKEN, CLIENT_CODE,task,debug=False, root=None,reconnect else: self.reconnect_max_delay = reconnect_max_delay - self.connect_timeout = connect_timeout + self.connect_timeout = connect_timeout + # Debug enables logs self.debug = debug @@ -252,6 +183,7 @@ def __init__(self, FEED_TOKEN, CLIENT_CODE,task,debug=False, root=None,reconnect self.on_reconnect = None self.on_noreconnect = None + def _create_connection(self, url, **kwargs): """Create a WebSocket client connection.""" self.factory = SmartSocketClientFactory(url, **kwargs) @@ -274,7 +206,6 @@ def _create_connection(self, url, **kwargs): self.factory.maxDelay = self.reconnect_max_delay self.factory.maxRetries = self.reconnect_max_tries - def connect(self, threaded=False, disable_ssl_verification=False, proxy=None): #print("Connect") self._create_connection(self.ROOT_URI) @@ -301,6 +232,7 @@ def connect(self, threaded=False, disable_ssl_verification=False, proxy=None): else: reactor.run(**opts) + def is_connected(self): #print("Check if WebSocket connection is established.") if self.ws and self.ws.state == self.ws.STATE_OPEN: @@ -327,26 +259,38 @@ def stop(self): def stop_retry(self): """Stop auto retry when it is in progress.""" if self.factory: - self.factory.stopTrying() + self.factory.stopTrying() + + def _on_reconnect(self, attempts_count): + if self.on_reconnect: + return self.on_reconnect(self, attempts_count) - def send_request(self,token): - if self.task in ("mw","sfi","dp"): + def _on_noreconnect(self): + if self.on_noreconnect: + return self.on_noreconnect(self) + + def websocket_connection(self): + if self.client_code == None or self.feed_token == None: + return "client_code or feed_token or task is missing" + + request={"task":"cn","channel":"","token":self.feed_token,"user":self.client_code,"acctid":self.client_code} + self.ws.sendMessage( + six.b(json.dumps(request)) + ) + print(request) + + threading.Thread(target=self.heartBeat,daemon=True).start() + + def send_request(self,token,task): + if task in ("mw","sfi","dp"): strwatchlistscrips = token #dynamic call try: - #print("Inside") - request={"task":"cn","channel":"","token":self.feed_token,"user":self.client_code,"acctid":self.client_code} - self.ws.sendMessage( - six.b(json.dumps(request)) - ) - #print(request) - request={"task":self.task,"channel":strwatchlistscrips,"token":self.feed_token,"user":self.client_code,"acctid":self.client_code} + request={"task":task,"channel":strwatchlistscrips,"token":self.feed_token,"user":self.client_code,"acctid":self.client_code} self.ws.sendMessage( six.b(json.dumps(request)) ) - threading.Thread(target=self.heartBeat,daemon=True).start() - #print(request) return True except Exception as e: self._close(reason="Error while request sending: {}".format(str(e))) @@ -355,9 +299,13 @@ def send_request(self,token): print("The task entered is invalid, Please enter correct task(mw,sfi,dp) ") def _on_connect(self, ws, response): + #print("-----_on_connect-------") self.ws = ws if self.on_connect: + + print(self.on_connect) self.on_connect(self, response) + #self.websocket_connection def _on_close(self, ws, code, reason): """Call `on_close` callback when connection is closed.""" @@ -373,6 +321,8 @@ def _on_error(self, ws, code, reason): if self.on_error: self.on_error(self, code, reason) + + def _on_message(self, ws, payload, is_binary): """Call `on_message` callback when text message is received.""" if self.on_message: @@ -387,7 +337,6 @@ def _on_message(self, ws, payload, is_binary): self._parse_text_message(payload) def _on_open(self, ws): - if not self._is_first_connect: self.connect() @@ -396,13 +345,6 @@ def _on_open(self, ws): if self.on_open: return self.on_open(self) - def _on_reconnect(self, attempts_count): - if self.on_reconnect: - return self.on_reconnect(self, attempts_count) - - def _on_noreconnect(self): - if self.on_noreconnect: - return self.on_noreconnect(self) def heartBeat(self): while True: @@ -416,6 +358,7 @@ def heartBeat(self): print("HeartBeats Failed") time.sleep(60) + def _parse_text_message(self, payload): """Parse text message.""" # Decode unicode data @@ -434,7 +377,7 @@ def _parse_text_message(self, payload): self.on_ticks(self, data) def _parse_binary(self, bin): - #print("""Parse binary data to a (list of) ticks structure.""") + """Parse binary data to a (list of) ticks structure.""" packets = self._split_packets(bin) # split data to individual ticks packet data = [] diff --git a/setup.py b/setup.py index 827dd5a..c737358 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ setup( name="smartapi-python", - version="1.2.0", + version="1.2.3", author="ab-smartapi", author_email="smartapi.sdk@gmail.com", description="Angel Broking openApi integration", From 1fb8531a94dd6d061d5cfa11e2c192477b538115 Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Wed, 31 Mar 2021 15:55:11 +0530 Subject: [PATCH 35/49] Changes in Readme --- README.md | 2 +- example/sample.py | 81 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 77 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 601923a..050dfd4 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ try: historicParam={ "exchange": "NSE", "symboltoken": "3045", - "interval": "MINUTE", + "interval": "ONE_MINUTE", "fromdate": "2021-02-08 09:00", "todate": "2021-02-08 09:16" } diff --git a/example/sample.py b/example/sample.py index 7764fd6..8cedc85 100644 --- a/example/sample.py +++ b/example/sample.py @@ -1,15 +1,20 @@ # package import statement -from smartapi.smartConnect import SmartConnect #from smartapi import SmartConnect +from smartapi import SmartConnect #or from smartapi.smartConnect import SmartConnect +#import smartapi.smartExceptions(for smartExceptions) + +#create object of call +obj=SmartConnect(api_key="your api key") -obj=SmartConnect() #login api call -data = obj.generateSession('Your Client Id','Password') +data = obj.generateSession("Your Client ID","Your Password") refreshToken= data['data']['refreshToken'] +#fetch the feedtoken +feedToken=obj.getfeedToken() + #fetch User Profile userProfile= obj.getProfile(refreshToken) - #place order try: orderparams = { @@ -30,10 +35,76 @@ print("The order id is: {}".format(orderId)) except Exception as e: print("Order placement failed: {}".format(e.message)) +#gtt rule creation +try: + gttCreateParams={ + "tradingsymbol" : "SBIN-EQ", + "symboltoken" : "3045", + "exchange" : "NSE", + "producttype" : "MARGIN", + "transactiontype" : "BUY", + "price" : 100000, + "qty" : 10, + "disclosedqty": 10, + "triggerprice" : 200000, + "timeperiod" : 365 + } + rule_id=gtt.gttCreateRule(gttCreateParams) + print("The GTT rule id is: {}".format(rule_id)) +except Exception as e: + print("GTT Rule creation failed: {}".format(e.message)) + +#gtt rule list +try: + status=["FORALL"] #should be a list + page=1 + count=10 + lists=smartApi.gttLists(status,page,count) +except Exception as e: + print("GTT Rule List failed: {}".format(e.message)) +#Historic api +try: + historicParam={ + "exchange": "NSE", + "symboltoken": "3045", + "interval": "ONE_MINUTE", + "fromdate": "2021-02-08 09:00", + "todate": "2021-02-08 09:16" + } + smartApi.getCandleData(historicParam) +except Exception as e: + print("Historic Api failed: {}".format(e.message)) #logout try: logout=obj.terminateSession('Your Client Id') print("Logout Successfull") except Exception as e: - print("Logout failed: {}".format(e.message)) \ No newline at end of file + print("Logout failed: {}".format(e.message)) + + + +## WebSocket +from smartapi import WebSocket +FEED_TOKEN= "your feed token" +CLIENT_CODE="your client Id" +token="channel you want the information of" #"nse_cm|2885&nse_cm|1594&nse_cm|11536" +task="task" #"mw"|"sfi"|"dp" +ss = WebSocket(FEED_TOKEN, CLIENT_CODE) + +def on_tick(ws, tick): + print("Ticks: {}".format(tick)) + +def on_connect(ws, response): + ws.websocket_connection() # Websocket connection + ws.send_request(token,task) + +def on_close(ws, code, reason): + ws.stop() + +# Assign the callbacks. +ss.on_ticks = on_tick +ss.on_connect = on_connect +ss.on_close = on_close + +ss.connect( ) From 893022aac3747dfb8b1a0c27d49c64b6437f2fb8 Mon Sep 17 00:00:00 2001 From: urvi-malde-190-at-244994576460 Date: Tue, 6 Apr 2021 16:53:17 +0530 Subject: [PATCH 36/49] New url added to webSocket.py --- SmartApi/webSocket.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SmartApi/webSocket.py b/SmartApi/webSocket.py index 2b82706..5364be6 100644 --- a/SmartApi/webSocket.py +++ b/SmartApi/webSocket.py @@ -133,7 +133,7 @@ class WebSocket(object): # Default reconnect attempts RECONNECT_MAX_TRIES = 50 - ROOT_URI='wss://omnefeeds.angelbroking.com/NestHtml5Mobile/socket/stream' + ROOT_URI='wss://wsfeeds.angelbroking.com/NestHtml5Mobile/socket/stream' # Flag to set if its first connect _is_first_connect = True From 3c2b33265ace0b132ce1fadd9109ca1b398dbb17 Mon Sep 17 00:00:00 2001 From: urvi-malde-190-at-244994576460 Date: Tue, 6 Apr 2021 20:40:08 +0530 Subject: [PATCH 37/49] New url added in webSocket.py --- SmartApi/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SmartApi/version.py b/SmartApi/version.py index 40c5528..530f4d2 100644 --- a/SmartApi/version.py +++ b/SmartApi/version.py @@ -2,7 +2,7 @@ __description__ = "Angel Broking openApi integration" __url__ = "https://www.angelbroking.com/" __download_url__ = "https://github.com/angelbroking-github/smartapi-python" -__version__ = "1.2.3" +__version__ = "1.2.4" __author__ = "ab-smartapi" __token__ = "ab-smartapi" __author_email__ = "smartapi.sdk@gmail.com" From a3ff1d5cf8aa801e6e03c37e927425d4385245f8 Mon Sep 17 00:00:00 2001 From: urvi-malde-190-at-244994576460 Date: Wed, 7 Apr 2021 15:15:05 +0530 Subject: [PATCH 38/49] Version changed in setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index c737358..599cbf9 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ setup( name="smartapi-python", - version="1.2.3", + version="1.2.4", author="ab-smartapi", author_email="smartapi.sdk@gmail.com", description="Angel Broking openApi integration", From 19a70ad2ff12e3589eaa3971f063c7063770db72 Mon Sep 17 00:00:00 2001 From: urvi-malde-190-at-244994576460 Date: Fri, 16 Apr 2021 19:10:42 +0530 Subject: [PATCH 39/49] changes in sample.py --- example/sample.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/example/sample.py b/example/sample.py index 8cedc85..2fc07f4 100644 --- a/example/sample.py +++ b/example/sample.py @@ -49,7 +49,7 @@ "triggerprice" : 200000, "timeperiod" : 365 } - rule_id=gtt.gttCreateRule(gttCreateParams) + rule_id=obj.gttCreateRule(gttCreateParams) print("The GTT rule id is: {}".format(rule_id)) except Exception as e: print("GTT Rule creation failed: {}".format(e.message)) @@ -59,7 +59,7 @@ status=["FORALL"] #should be a list page=1 count=10 - lists=smartApi.gttLists(status,page,count) + lists=obj.gttLists(status,page,count) except Exception as e: print("GTT Rule List failed: {}".format(e.message)) @@ -72,7 +72,7 @@ "fromdate": "2021-02-08 09:00", "todate": "2021-02-08 09:16" } - smartApi.getCandleData(historicParam) + obj.getCandleData(historicParam) except Exception as e: print("Historic Api failed: {}".format(e.message)) #logout From 89dfbec704bcddabdd63609bf25e9df124f1b73a Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Wed, 21 Apr 2021 10:07:14 +0530 Subject: [PATCH 40/49] changes in readme and sample.py for websocket termination issue(multiprocess introduced) --- README.md | 8 ++++++-- example/sample.py | 8 ++++++-- test/test.py | 8 ++++++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 050dfd4..bf01dea 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,9 @@ except Exception as e: ## WebSocket -from smartapi import WebSocket +from smartapi import WebSocket +import multiprocessing +import sys FEED_TOKEN= "your feed token" CLIENT_CODE="your client Id" token="channel you want the information of" #"nse_cm|2885&nse_cm|1594&nse_cm|11536" @@ -122,7 +124,9 @@ ss.on_ticks = on_tick ss.on_connect = on_connect ss.on_close = on_close -ss.connect( ) +p1 = multiprocessing.Process(target = ss.connect()) +sys.exit() +p1.start() diff --git a/example/sample.py b/example/sample.py index 2fc07f4..13a64c2 100644 --- a/example/sample.py +++ b/example/sample.py @@ -85,7 +85,9 @@ ## WebSocket -from smartapi import WebSocket +from smartapi import WebSocket +import multiprocessing +import sys FEED_TOKEN= "your feed token" CLIENT_CODE="your client Id" token="channel you want the information of" #"nse_cm|2885&nse_cm|1594&nse_cm|11536" @@ -107,4 +109,6 @@ def on_close(ws, code, reason): ss.on_connect = on_connect ss.on_close = on_close -ss.connect( ) +p1 = multiprocessing.Process(target = ss.connect()) +sys.exit() +p1.start() diff --git a/test/test.py b/test/test.py index 2f6f8c1..f2f5f27 100644 --- a/test/test.py +++ b/test/test.py @@ -112,13 +112,15 @@ smartApi.gttDetails(rule_id) -smartApi.gttLists('List of status',,) +smartApi.gttLists('List of status','','') smartApi.terminateSession('Your Client Id') ## Websocket Programming from smartapi import WebSocket +import multiprocessing +import sys FEED_TOKEN=feedToken CLIENT_CODE="Your Client Id" token=None @@ -138,4 +140,6 @@ def on_close(ws, code, reason): ss.on_connect = on_connect ss.on_close = on_close -ss.connect( ) \ No newline at end of file +p1 = multiprocessing.Process(target = ss.connect()) +sys.exit() +p1.start() \ No newline at end of file From 02b5dc1a2689a584afcd572bab1f6586477e1e40 Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Mon, 26 Apr 2021 12:09:13 +0530 Subject: [PATCH 41/49] changes in heartbeat seconds --- README.md | 12 ++++++------ SmartApi/version.py | 2 +- SmartApi/webSocket.py | 2 +- example/sample.py | 9 ++++----- setup.py | 2 +- 5 files changed, 13 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index bf01dea..f5b8848 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,10 @@ from smartapi import SmartConnect #or from smartapi.smartConnect import SmartCon #import smartapi.smartExceptions(for smartExceptions) #create object of call -obj=SmartConnect(api_key="your api key") +obj=SmartConnect(api_key="your api key", + #optional + #access_token = "your access token", + #refresh_token = "your refresh_token") #login api call @@ -101,8 +104,7 @@ except Exception as e: ## WebSocket from smartapi import WebSocket -import multiprocessing -import sys + FEED_TOKEN= "your feed token" CLIENT_CODE="your client Id" token="channel you want the information of" #"nse_cm|2885&nse_cm|1594&nse_cm|11536" @@ -124,9 +126,7 @@ ss.on_ticks = on_tick ss.on_connect = on_connect ss.on_close = on_close -p1 = multiprocessing.Process(target = ss.connect()) -sys.exit() -p1.start() +ss.connect() diff --git a/SmartApi/version.py b/SmartApi/version.py index 530f4d2..6b36fad 100644 --- a/SmartApi/version.py +++ b/SmartApi/version.py @@ -2,7 +2,7 @@ __description__ = "Angel Broking openApi integration" __url__ = "https://www.angelbroking.com/" __download_url__ = "https://github.com/angelbroking-github/smartapi-python" -__version__ = "1.2.4" +__version__ = "1.2.5" __author__ = "ab-smartapi" __token__ = "ab-smartapi" __author_email__ = "smartapi.sdk@gmail.com" diff --git a/SmartApi/webSocket.py b/SmartApi/webSocket.py index 5364be6..8d03897 100644 --- a/SmartApi/webSocket.py +++ b/SmartApi/webSocket.py @@ -356,7 +356,7 @@ def heartBeat(self): except: print("HeartBeats Failed") - time.sleep(60) + time.sleep(30) def _parse_text_message(self, payload): diff --git a/example/sample.py b/example/sample.py index 13a64c2..9aca435 100644 --- a/example/sample.py +++ b/example/sample.py @@ -86,8 +86,7 @@ ## WebSocket from smartapi import WebSocket -import multiprocessing -import sys + FEED_TOKEN= "your feed token" CLIENT_CODE="your client Id" token="channel you want the information of" #"nse_cm|2885&nse_cm|1594&nse_cm|11536" @@ -109,6 +108,6 @@ def on_close(ws, code, reason): ss.on_connect = on_connect ss.on_close = on_close -p1 = multiprocessing.Process(target = ss.connect()) -sys.exit() -p1.start() +ss.connect() + + diff --git a/setup.py b/setup.py index 599cbf9..73e0cc2 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ setup( name="smartapi-python", - version="1.2.4", + version="1.2.5", author="ab-smartapi", author_email="smartapi.sdk@gmail.com", description="Angel Broking openApi integration", From a908b067e6c46dd38b59a5571aeb6e25776e48db Mon Sep 17 00:00:00 2001 From: Vrushali Kapse Date: Mon, 10 May 2021 16:50:20 +0530 Subject: [PATCH 42/49] Changes in websocket heartbeat secs --- SmartApi/version.py | 2 +- SmartApi/webSocket.py | 4 ++-- setup.py | 2 +- test/test.py | 1 + 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/SmartApi/version.py b/SmartApi/version.py index 6b36fad..78d56e9 100644 --- a/SmartApi/version.py +++ b/SmartApi/version.py @@ -2,7 +2,7 @@ __description__ = "Angel Broking openApi integration" __url__ = "https://www.angelbroking.com/" __download_url__ = "https://github.com/angelbroking-github/smartapi-python" -__version__ = "1.2.5" +__version__ = "1.2.6" __author__ = "ab-smartapi" __token__ = "ab-smartapi" __author_email__ = "smartapi.sdk@gmail.com" diff --git a/SmartApi/webSocket.py b/SmartApi/webSocket.py index 8d03897..c98b1ea 100644 --- a/SmartApi/webSocket.py +++ b/SmartApi/webSocket.py @@ -277,7 +277,7 @@ def websocket_connection(self): self.ws.sendMessage( six.b(json.dumps(request)) ) - print(request) + #print(request) threading.Thread(target=self.heartBeat,daemon=True).start() @@ -356,7 +356,7 @@ def heartBeat(self): except: print("HeartBeats Failed") - time.sleep(30) + time.sleep(60) def _parse_text_message(self, payload): diff --git a/setup.py b/setup.py index 73e0cc2..a4ef758 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ setup( name="smartapi-python", - version="1.2.5", + version="1.2.6", author="ab-smartapi", author_email="smartapi.sdk@gmail.com", description="Angel Broking openApi integration", diff --git a/test/test.py b/test/test.py index f2f5f27..57267d6 100644 --- a/test/test.py +++ b/test/test.py @@ -130,6 +130,7 @@ def on_tick(ws, tick): print("Ticks: {}".format(tick)) def on_connect(ws, response): + ws.websocket_connection() ws.send_request(token,task) def on_close(ws, code, reason): From 6fba8684b6c40576bf46baeb95b939fd410c59ef Mon Sep 17 00:00:00 2001 From: Suraj Datta Date: Thu, 27 May 2021 19:55:38 +0530 Subject: [PATCH 43/49] WS fixes --- .gitignore | 1 + README.md | 47 +++++--- SmartApi/__init__.py | 5 +- SmartApi/smartApiWebsocket.py | 182 +++++++++++++++++++++++++++++++ example/smartwebsocketexample.py | 38 +++++++ 5 files changed, 253 insertions(+), 20 deletions(-) create mode 100644 SmartApi/smartApiWebsocket.py create mode 100644 example/smartwebsocketexample.py diff --git a/.gitignore b/.gitignore index 8b13789..3953ffd 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ +.pypirc \ No newline at end of file diff --git a/README.md b/README.md index f5b8848..381491a 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ Use the package manager [pip](https://pip.pypa.io/en/stable/) to install smartap ```bash pip install smartapi-python +pip install websocket-client ``` ## Usage @@ -99,35 +100,45 @@ try: print("Logout Successfull") except Exception as e: print("Logout failed: {}".format(e.message)) +``` +## Getting started with SmartAPI Websocket's +```python -## WebSocket -from smartapi import WebSocket +from smartapiwebsocket import SmartWebSocket -FEED_TOKEN= "your feed token" -CLIENT_CODE="your client Id" -token="channel you want the information of" #"nse_cm|2885&nse_cm|1594&nse_cm|11536" -task="task" #"mw"|"sfi"|"dp" -ss = WebSocket(FEED_TOKEN, CLIENT_CODE) +# feed_token=092017047 +FEED_TOKEN="YOUR_FEED_TOKEN" +CLIENT_CODE="YOUR_CLIENT_CODE" +# token="mcx_fo|224395" +token="EXCHANGE|TOKEN_SYMBOL" #SAMPLE: nse_cm|2885&nse_cm|1594&nse_cm|11536&nse_cm|3045 +# token="mcx_fo|226745&mcx_fo|220822&mcx_fo|227182&mcx_fo|221599" +task="mw" # mw|sfi|dp -def on_tick(ws, tick): - print("Ticks: {}".format(tick)) +ss = SmartWebSocket(FEED_TOKEN, CLIENT_CODE) -def on_connect(ws, response): - ws.websocket_connection() # Websocket connection - ws.send_request(token,task) +def on_message(ws, message): + print("Ticks: {}".format(message)) + +def on_open(ws): + print("on open") + ss.subscribe(task,token) -def on_close(ws, code, reason): - ws.stop() +def on_error(ws, error): + print(error) + +def on_close(ws): + print("Close") # Assign the callbacks. -ss.on_ticks = on_tick -ss.on_connect = on_connect -ss.on_close = on_close +ss._on_open = on_open +ss._on_message = on_message +ss._on_error = on_error +ss._on_close = on_close ss.connect() - +``` diff --git a/SmartApi/__init__.py b/SmartApi/__init__.py index 4ddea18..720c816 100644 --- a/SmartApi/__init__.py +++ b/SmartApi/__init__.py @@ -1,9 +1,10 @@ from __future__ import unicode_literals,absolute_import from smartapi.smartConnect import SmartConnect -from smartapi.webSocket import WebSocket +# from smartapi.webSocket import WebSocket +from smartapi.smartApiWebsocket import SmartWebSocket -__all__ = ["SmartConnect","WebSocket"] +__all__ = ["SmartConnect","SmartWebSocket"] diff --git a/SmartApi/smartApiWebsocket.py b/SmartApi/smartApiWebsocket.py new file mode 100644 index 0000000..723f680 --- /dev/null +++ b/SmartApi/smartApiWebsocket.py @@ -0,0 +1,182 @@ +# -*- coding: utf-8 -*- +""" +Created on Fri Apr 23 11:38:36 2021 + +@author: Sandip.Khairnar +""" + +import websocket +import six +import base64 +import zlib +import datetime +import time +import json +import threading +import ssl + +class SmartWebSocket(object): + ROOT_URI='wss://wsfeeds.angelbroking.com/NestHtml5Mobile/socket/stream' + HB_INTERVAL=30 + HB_THREAD_FLAG=False + WS_RECONNECT_FLAG=False + feed_token=None + client_code=None + ws=None + task_dict = {} + + def __init__(self, FEED_TOKEN, CLIENT_CODE): + self.root = self.ROOT_URI + self.feed_token = FEED_TOKEN + self.client_code = CLIENT_CODE + if self.client_code == None or self.feed_token == None: + return "client_code or feed_token or task is missing" + + def _subscribe_on_open(self): + request = {"task": "cn", "channel": "NONLM", "token": self.feed_token, "user": self.client_code, + "acctid": self.client_code} + print(request) + self.ws.send( + six.b(json.dumps(request)) + ) + + thread = threading.Thread(target=self.run, args=()) + thread.daemon = True + thread.start() + + def run(self): + while True: + # More statements comes here + if self.HB_THREAD_FLAG: + break + print(datetime.datetime.now().__str__() + ' : Start task in the background') + + self.heartBeat() + + time.sleep(self.HB_INTERVAL) + + def subscribe(self, task, token): + # print(self.task_dict) + self.task_dict.update([(task,token),]) + # print(self.task_dict) + if task in ("mw", "sfi", "dp"): + strwatchlistscrips = token # dynamic call + + try: + request = {"task": task, "channel": strwatchlistscrips, "token": self.feed_token, + "user": self.client_code, "acctid": self.client_code} + + self.ws.send( + six.b(json.dumps(request)) + ) + return True + except Exception as e: + self._close(reason="Error while request sending: {}".format(str(e))) + raise + else: + print("The task entered is invalid, Please enter correct task(mw,sfi,dp) ") + + def resubscribe(self): + for task, marketwatch in self.task_dict.items(): + print(task, '->', marketwatch) + try: + request = {"task": task, "channel": marketwatch, "token": self.feed_token, + "user": self.client_code, "acctid": self.client_code} + + self.ws.send( + six.b(json.dumps(request)) + ) + return True + except Exception as e: + self._close(reason="Error while request sending: {}".format(str(e))) + raise + + def heartBeat(self): + try: + request = {"task": "hb", "channel": "", "token": self.feed_token, "user": self.client_code, + "acctid": self.client_code} + print(request) + self.ws.send( + six.b(json.dumps(request)) + ) + + except: + print("HeartBeat Sending Failed") + # time.sleep(60) + + def _parse_text_message(self, message): + """Parse text message.""" + + data = base64.b64decode(message) + + try: + data = bytes((zlib.decompress(data)).decode("utf-8"), 'utf-8') + data = json.loads(data.decode('utf8').replace("'", '"')) + data = json.loads(json.dumps(data, indent=4, sort_keys=True)) + except ValueError: + return + + # return data + if data: + self._on_message(self.ws,data) + + def connect(self): + # websocket.enableTrace(True) + self.ws = websocket.WebSocketApp(self.ROOT_URI, + on_message=self.__on_message, + on_close=self.__on_close, + on_open=self.__on_open, + on_error=self.__on_error) + + self.ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE}) + + def __on_message(self, ws, message): + self._parse_text_message(message) + # print(msg) + + def __on_open(self, ws): + print("__on_open################") + self.HB_THREAD_FLAG = False + self._subscribe_on_open() + if self.WS_RECONNECT_FLAG: + self.WS_RECONNECT_FLAG = False + self.resubscribe() + else: + self._on_open(ws) + + def __on_close(self, ws): + self.HB_THREAD_FLAG = True + print("__on_close################") + self._on_close(ws) + + def __on_error(self, ws, error): + + if ( "timed" in str(error) ) or ( "Connection is already closed" in str(error) ): + + self.WS_RECONNECT_FLAG = True + self.HB_THREAD_FLAG = True + + if (ws is not None): + ws.close() + ws.on_message = None + ws.on_open = None + ws.close = None + # print (' deleting ws') + del ws + + self.connect() + else: + print ('Error info: %s' %(error)) + self._on_error(ws, error) + + def _on_message(self, ws, message): + pass + + def _on_open(self, ws): + pass + + def _on_close(self, ws): + pass + + def _on_error(self, ws, error): + pass \ No newline at end of file diff --git a/example/smartwebsocketexample.py b/example/smartwebsocketexample.py new file mode 100644 index 0000000..fe620c4 --- /dev/null +++ b/example/smartwebsocketexample.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +""" +Created on Wed May 26 18:50:44 2021 + +@author: Sandip.Khairnar +""" + +from smartapiwebsocket import SmartWebSocket + +# feed_token=092017047 +FEED_TOKEN="092017047" +CLIENT_CODE="S212741" +# token="mcx_fo|224395" +token="nse_cm|2885&nse_cm|1594&nse_cm|11536&nse_cm|3045" +# token="mcx_fo|226745&mcx_fo|220822&mcx_fo|227182&mcx_fo|221599" +task="mw" +ss = SmartWebSocket(FEED_TOKEN, CLIENT_CODE) + +def on_message(ws, message): + print("Ticks: {}".format(message)) + +def on_open(ws): + print("on open") + ss.subscribe(task,token) + +def on_error(ws, error): + print(error) + +def on_close(ws): + print("Close") + +# Assign the callbacks. +ss._on_open = on_open +ss._on_message = on_message +ss._on_error = on_error +ss._on_close = on_close + +ss.connect() \ No newline at end of file From ba9db40160e888bb6ea43934d5c76516de586e10 Mon Sep 17 00:00:00 2001 From: Suraj Datta Date: Thu, 27 May 2021 20:53:43 +0530 Subject: [PATCH 44/49] fixes --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index a4ef758..d34b4b4 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ setup( name="smartapi-python", - version="1.2.6", + version="1.2.7", author="ab-smartapi", author_email="smartapi.sdk@gmail.com", description="Angel Broking openApi integration", From ff5f1c284f56a66b8f8562b178a80e88691279f9 Mon Sep 17 00:00:00 2001 From: dsuraj72 Date: Fri, 28 May 2021 12:17:17 +0530 Subject: [PATCH 45/49] Delete .pypirc --- .pypirc | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 .pypirc diff --git a/.pypirc b/.pypirc deleted file mode 100644 index 13da8a9..0000000 --- a/.pypirc +++ /dev/null @@ -1,10 +0,0 @@ -[distutils] -index-servers = - pypi - -[pypi] -repository: https://upload.pypi.org/legacy/ -username: ab-smartapi -password: Smart#54321 - - From 86859f8d2654596b740e8190672d9ba91b6cdaa6 Mon Sep 17 00:00:00 2001 From: dsuraj72 Date: Fri, 28 May 2021 12:19:39 +0530 Subject: [PATCH 46/49] Update README.md readme updated --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 381491a..8986177 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,7 @@ except Exception as e: ## Getting started with SmartAPI Websocket's ```python -from smartapiwebsocket import SmartWebSocket +from smartapi import SmartWebSocket # feed_token=092017047 FEED_TOKEN="YOUR_FEED_TOKEN" From 8ffd927b6b8d359e3fe75d6ae16719357040b2f0 Mon Sep 17 00:00:00 2001 From: Suraj Datta Date: Tue, 15 Jun 2021 20:24:20 +0530 Subject: [PATCH 47/49] connection new fix --- README.md | 6 +++--- SmartApi/smartApiWebsocket.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 8986177..095b325 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ try: "triggerprice" : 200000, "timeperiod" : 365 } - rule_id=gtt.gttCreateRule(gttCreateParams) + rule_id=obj.gttCreateRule(gttCreateParams) print("The GTT rule id is: {}".format(rule_id)) except Exception as e: print("GTT Rule creation failed: {}".format(e.message)) @@ -78,7 +78,7 @@ try: status=["FORALL"] #should be a list page=1 count=10 - lists=smartApi.gttLists(status,page,count) + lists=obj.gttLists(status,page,count) except Exception as e: print("GTT Rule List failed: {}".format(e.message)) @@ -91,7 +91,7 @@ try: "fromdate": "2021-02-08 09:00", "todate": "2021-02-08 09:16" } - smartApi.getCandleData(historicParam) + obj.getCandleData(historicParam) except Exception as e: print("Historic Api failed: {}".format(e.message)) #logout diff --git a/SmartApi/smartApiWebsocket.py b/SmartApi/smartApiWebsocket.py index 723f680..c21ca44 100644 --- a/SmartApi/smartApiWebsocket.py +++ b/SmartApi/smartApiWebsocket.py @@ -151,7 +151,7 @@ def __on_close(self, ws): def __on_error(self, ws, error): - if ( "timed" in str(error) ) or ( "Connection is already closed" in str(error) ): + if ( "timed" in str(error) ) or ( "Connection is already closed" in str(error) or ( "Connection to remote host was lost" in str(error) ): self.WS_RECONNECT_FLAG = True self.HB_THREAD_FLAG = True From 982313254d582464c2b91eb95556dad9d33cd914 Mon Sep 17 00:00:00 2001 From: dsuraj72 Date: Tue, 15 Jun 2021 21:15:31 +0530 Subject: [PATCH 48/49] version upgraded --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index d34b4b4..88e1908 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ setup( name="smartapi-python", - version="1.2.7", + version="1.2.8", author="ab-smartapi", author_email="smartapi.sdk@gmail.com", description="Angel Broking openApi integration", From 7f543a8e6a4ddc9440c323156e9295b0a43387e4 Mon Sep 17 00:00:00 2001 From: dsuraj72 Date: Wed, 16 Jun 2021 10:18:41 +0530 Subject: [PATCH 49/49] syntax fix --- SmartApi/smartApiWebsocket.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SmartApi/smartApiWebsocket.py b/SmartApi/smartApiWebsocket.py index c21ca44..f5c7b18 100644 --- a/SmartApi/smartApiWebsocket.py +++ b/SmartApi/smartApiWebsocket.py @@ -151,7 +151,7 @@ def __on_close(self, ws): def __on_error(self, ws, error): - if ( "timed" in str(error) ) or ( "Connection is already closed" in str(error) or ( "Connection to remote host was lost" in str(error) ): + if ( "timed" in str(error) ) or ( "Connection is already closed" in str(error) ) or ( "Connection to remote host was lost" in str(error) ): self.WS_RECONNECT_FLAG = True self.HB_THREAD_FLAG = True