Skip to content

Commit

Permalink
Added ticker functionality, can stream data feeds from market
Browse files Browse the repository at this point in the history
  • Loading branch information
iamkrish-coder committed Jun 29, 2023
1 parent 2735bc2 commit abe735a
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 12 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -371,3 +371,4 @@ FodyWeavers.xsd
/IntelliTrader/src/output/request_token_2123.txt
/IntelliTrader/src/output/access_token_2108.txt
/IntelliTrader/src/output/request_token_2108.txt
/IntelliTrader/src/output
27 changes: 20 additions & 7 deletions IntelliTrader/IntelliTrader.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@

from kiteconnect import KiteConnect
from kiteconnect import KiteTicker
from src.connection import Connection
from src.helper import Helper
from src.fetch import Fetch
from src.orders import Orders
from src.ticker import Ticker
import os
import glob
import datetime
Expand All @@ -12,7 +14,7 @@

# Create and configure logger
logging.basicConfig(
level=logging.INFO,
level=logging.NOTSET,
format='%(asctime)s [%(levelname)s] #%(lineno)s - %(module)s - Message: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S')

Expand All @@ -24,22 +26,23 @@

if os.path.isfile(access_token_file):
# Generate trading session
api_key=config[0]
access_token = open('./src/output/access_token' + '_' + auth_date + '.txt','r').read()
kite = KiteConnect(api_key=config[0])
kite = KiteConnect(api_key)
kite_ticker = KiteTicker(api_key, access_token)
kite.set_access_token(access_token)
logging.info("Connected to Kite")
logging.info("Connected to Kite with Ticker Data")
else:
# Remove old access token and request token before generating new one
old_access_token_files = glob.glob('./src/output/access_token*.txt')
old_request_token_files = glob.glob('./src/output/request_token*.txt')

for old_access_token_file in old_access_token_files:
try:
os.remove(old_access_token_file)
except:
logging.error("Error while deleting file : ", old_access_token_file)
exit()

old_request_token_files = glob.glob('./src/output/request_token*.txt')
for old_request_token_file in old_request_token_files:
try:
os.remove(old_request_token_file)
Expand All @@ -49,16 +52,26 @@

# Begin a new connection
connect = Connection(config)
kite, access_token = connect.broker_login(KiteConnect, logging)
kite, kite_ticker, access_token = connect.broker_login(KiteConnect, KiteTicker, logging)
kite.set_access_token(access_token)
logging.info("Connected to Kite")
logging.info("Connected to Kite with Ticker Data")

connection_kit = {
"kite" : kite,
"kiteticker": kite_ticker,
"authorize" : access_token,
"log" : logging
}

help = Helper(connection_kit)
fetch = Fetch(connection_kit)
orders = Orders(connection_kit)
ticker = Ticker(connection_kit)

ticker_exchange = ''
ticker_symbol = ''
ticker_mode = ''
user_settings = []

itoken = fetch.stream_instrument_token_lookup(ticker_exchange, ticker_symbol)
ticker.connect_to_ticker(itoken, ticker_mode, user_settings)
2 changes: 2 additions & 0 deletions IntelliTrader/IntelliTrader.pyproj
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
<Compile Include="IntelliTrader.py" />
<Compile Include="src\modify.py" />
<Compile Include="src\orders.py" />
<Compile Include="src\ticker.py" />
<Compile Include="src\ticker.py" />
</ItemGroup>
<ItemGroup>
<Folder Include="src\driver\" />
Expand Down
7 changes: 5 additions & 2 deletions IntelliTrader/src/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class Connection:
def __init__(self, params):
self.prop = params

def broker_login(self, KiteConnect, logging):
def broker_login(self, KiteConnect, KiteTicker, logging):
# Assign properties
api_key = self.prop[0]
secret_key = self.prop[1]
Expand Down Expand Up @@ -88,6 +88,9 @@ def broker_login(self, KiteConnect, logging):
Helper.write_text_output('access_token' + '_' + auth_date + '.txt', access_token)
logging.info("Kite access_token generated successfully")

# Kite Ticker Subscription
kite_ticker = KiteTicker(api_key, access_token)

driver.quit()

return kite, access_token
return kite, kite_ticker, access_token
19 changes: 16 additions & 3 deletions IntelliTrader/src/fetch.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def fetch_instruments(self, exchange=None):
return instruments_dump

# Lookup instrument token
def instrument_lookup(self, exchange, symbol):
def instrument_token_lookup(self, exchange, symbol):
nse_instruments_dump = self.prop['kite'].instruments(exchange)
instrument_df = pd.DataFrame(nse_instruments_dump)
try:
Expand All @@ -30,10 +30,23 @@ def instrument_lookup(self, exchange, symbol):
except:
self.prop['log'].warning('Please verify that the symbol name [%s] is present in the specified exchange.' %(symbol))
exit()

# Lookup instrument token list (web streaming)
def stream_instrument_token_lookup(self, exchange, symbol_list):
nse_instruments_dump = self.prop['kite'].instruments(exchange)
instrument_df = pd.DataFrame(nse_instruments_dump)
token_list = []
try:
for symbol in symbol_list:
token_list.append(int(instrument_df[instrument_df.tradingsymbol == symbol].instrument_token.values[0]))
return token_list
except:
self.prop['log'].warning('Please verify that the symbol name [%s] is present in the specified exchange.' %(symbol))
exit()

# Fetch historical data for an exchange and symbol
def fetch_ohlc(self, exchange, symbol, interval, duration):
instrument_token = self.instrument_lookup(exchange, symbol)
instrument_token = self.instrument_token_lookup(exchange, symbol)
data = pd.DataFrame(self.prop['kite'].historical_data(instrument_token, dt.date.today()-dt.timedelta(duration), dt.date.today(), interval))
Helper.write_csv_output('historical_' + exchange + '_' + symbol + '.csv', data)
return data
Expand Down Expand Up @@ -61,7 +74,7 @@ def fetch_ohlc_extended(self, exchange, symbol, period_start, interval):
lookback_period_threshold = 1


instrument_token = self.instrument_lookup(exchange, symbol)
instrument_token = self.instrument_token_lookup(exchange, symbol)
start_date = dt.datetime.strptime(period_start, '%d-%m-%Y')
end_date = dt.date.today()
data = pd.DataFrame(columns=['date', 'open', 'high', 'low', 'close', 'volume'])
Expand Down
103 changes: 103 additions & 0 deletions IntelliTrader/src/ticker.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import pandas as pd
import os
import datetime as dt
import time
from src.helper import Helper

class Ticker:
def __init__(self, params):
self.prop = params
self.tokens = []
self.ticker_data = []

# Callback for successful connection.
def on_connect(self, ws, response):
self.prop['log'].info("Successfully connected. Response: {}".format(response))
ws.subscribe(self.tokens)

if self.mode == "ltp":
ticker_mode = ws.MODE_LTP
elif self.mode == "quote":
ticker_mode = ws.MODE_QUOTE
elif self.mode == "full":
ticker_mode = ws.MODE_FULL
else:
self.prop['log'].warn("No ticker mode is defined: {}".format(ticker_mode))

ws.set_mode(ticker_mode, self.tokens)
self.prop['log'].info("Subscribe to tokens in Full/LTP/Quote mode: {}".format(self.tokens))


# Callback when current connection is closed.
def on_close(self, ws, code, reason):
self.prop['log'].info("Connection closed: {code} - {reason}".format(code=code, reason=reason))
#ws.stop()

# Callback when connection closed with error.
def on_error(self, ws, code, reason):
self.prop['log'].info("Connection error: {code} - {reason}".format(code=code, reason=reason))


# Callback when reconnect is on progress
def on_reconnect(self, ws, attempts_count):
self.prop['log'].info("Reconnecting: {}".format(attempts_count))


# Callback when all reconnect failed (exhausted max retries)
def on_noreconnect(self, ws):
self.prop['log'].info("Reconnect failed.")

# Callback for tick reception.
def on_ticks(self, ws, ticks):
if len(ticks) > 0:
#self.prop['log'].info("Current mode: {}".format(ticks[0]["mode"]))
self.ticker_data.extend(ticks)
self.process_ticker_data(ws)


# Process the stored ticker data or perform any required operations
def process_ticker_data(self, ws):
for tick in self.ticker_data:
print("Ticks: {}".format(tick))
time.sleep(1)

if dt.datetime.now().time() >= self.exit_time:
ws.stop() # Close the connection at a specific time

target_profit = self.target_profit
if tick[-1]['last_price'] >= target_profit:
ws.stop() # Close the connection when target price is reached

stop_loss = self.stop_loss
if tick[-1]['last_price'] <= stop_loss:
ws.stop() # Close the connection when stop loss is triggered

entry_price = self.entry_price
target_profit_points = self.target_profit_points
if tick[-1]['last_price'] >= entry_price + target_profit_points:
ws.stop() # Close the connection when profit target is reached

def connect_to_ticker(self, tokens, mode, user_settings):
self.tokens = tokens
self.mode = mode
self.exit_time = dt.time(15,30)
self.entry_price = user_settings.en_price
self.target_profit = user_settings.tp_price
self.stop_loss = user_settings.sl_price
self.target_profit_points = user_settings.tp_points
self.stop_loss_points = user_settings.sl_points

# Assign the callbacks
self.prop['kiteticker'].on_connect = self.on_connect
self.prop['kiteticker'].on_reconnect = self.on_reconnect
self.prop['kiteticker'].on_noreconnect = self.on_noreconnect
self.prop['kiteticker'].on_ticks = self.on_ticks
self.prop['kiteticker'].on_close = self.on_close
self.prop['kiteticker'].on_error = self.on_error

self.prop['kiteticker'].connect(threaded=True, disable_ssl_verification=True)

while True:
if self.prop['kiteticker'].is_connected():
self.prop['kiteticker'].set_mode(self.mode, self.tokens)
time.sleep(1)

0 comments on commit abe735a

Please sign in to comment.