import sys
sys.path.append("C:\\Users\\explrorer\\Desktop\\PaytmAPIsTrading\\PaytmApiUtils")
sys.path.append("C:\\Users\\explrorer\\Desktop\\PaytmAPIsTrading")
import dash
from dash import Dash, html, dcc, Input, Output, callback
from websocketclient import setUpTokens, websocketOption
from optiondashboard_utils import getInstruments, getStrikeRanges, setUpWebsocketClients, updateStrikeRange
from datetime import date
import logging
import pandas as pd
from processQuotesSql import processLiveQuotes
import multiprocessing as mp
logging.basicConfig(level=logging.INFO)
def generateAppLayout(strike_range, option_expiry_dates):
range_sliders_elements = []
for expDate in option_expiry_dates:
range_sliders_elements += [ html.P(f"Select Range of strikes to consider for Optio Expiry({expDate.strftime('%Y-%m-%d')}):"),
dcc.RangeSlider(strike_range[expDate][0], strike_range[expDate][-1], 50, value=[strike_range[expDate][0], strike_range[expDate][-1]], id=f"my-range-slider-{expDate.strftime('%Y-%m-%d')}") ]
input_attribute_callback = []
for expDate in option_expiry_dates:
input_attribute_callback.append( Input(f"my-range-slider-{expDate.strftime('%Y-%m-%d')}", 'value') )
app = Dash(__name__)
app.layout = html.Div([html.Div(children='Option Quotes Downloader'),] + range_sliders_elements + [html.Div(id='output-container-range-slider')])
return app, input_attribute_callback
if __name__ == '__main__':
option_expiry_dates = [date(2024,1,11), date(2024,1,18), date(2024,1,25), date(2024,2,29), date(2024,3,28)]
fut_expiries = [date(2024,1,25), date(2024,2,29), date(2024,3,28)]
symbol = 'NIFTY'
setUpTokens()
strike_range = getStrikeRanges(option_expiry_dates)
instruments_to_consider = getInstruments( option_expiry_dates, fut_expiries, strike_range)
app, input_attribute_callback = generateAppLayout(strike_range, option_expiry_dates)
write_q = mp.Queue()
# starting this first so that the process is ready before websockets starts inserting the data into the mp.queue
process_quotes_sql_process = mp.Process(target = processLiveQuotes, args = (write_q,))
process_quotes_sql_process.start()
websocketsForOptions, webSocketForFutsAndIdx, threadsForOptions, threadsForFutsAndIdx = setUpWebsocketClients(option_expiry_dates, fut_expiries, instruments_to_consider, write_q)
@callback( Output('output-container-range-slider', 'children'), tuple(input_attribute_callback) )
def update_strike_range(*args):
out = ""
for expDate, strike_range_expDate in zip(option_expiry_dates, args):
if (( strike_range_expDate[0] != strike_range[expDate][0] ) or (strike_range_expDate[1] != strike_range[expDate][1])):
# we need to update the strike range for this expiry date
websocketsForOptions = updateStrikeRange(expDate, strike_range_expDate, websocketsForOptions, threadsForOptions, instruments_to_consider, strike_range, write_q)
out += f"Updated Strike Range for Expiry({expDate.strftime('%Y-%m-%d')}) to ({strike_range_expDate[0]},{strike_range_expDate[1]})\n"
return out
print(f"I am {__name__} process")
app.run(debug=True, port = 9000)
The print statement is appearing twice
I am main process
I am main process
where both of the times name = main. I thought that if app.run indeed spawns a parallel process, it will not execute the content inside of main block but that is not the case, what can be done here?
I am creating several websocket connections inside the main process itself and a separate process to execute the messages of those websockets and I don’t want to recreate those connections.