def connection_interface_simulation(self): """ Connection signal-slot in interface Simulation :return: None """ # btn select criteria Simulator self.btn_selectAllCriteria_2.clicked.connect( Slots.select_all_criteria_simulator) # btn deselect criteria Simulator self.btn_deselectAllCriteria_2.clicked.connect( Slots.deselect_all_criteria_simulator) # link slider and spin box of box layout to left HelperFunctionQt.link_spin_slider_layout(self.verticalLayout_left_2) # link slider and spin box of box layout to right HelperFunctionQt.link_spin_slider_layout(self.verticalLayout_right_2) # connect min max datetime self.dateEdit_simulatorFrom.dateTimeChanged.connect( self.dateEdit_simulatorTo.setMinimumDateTime) self.dateEdit_simulatorTo.dateTimeChanged.connect( self.dateEdit_simulatorFrom.setMaximumDateTime) # btn for open pop-up to set params within type simulator selected self.btn_setParamsSimulation.clicked.connect( Slots.open_windows_setting_params_simulation) # btn for start simulation self.btn_startSimulation.clicked.connect(Slots.start_simulation) # btn for show report of simulation self.btn_showReport.clicked.connect(Slots.show_report) # clear old params of type simulation self.comboBox_typeSimulation.currentIndexChanged.connect( dict_params_value_sim.clear) # Set max combobox commission depending if is in % or $ self.comboBox_commissionPctDollar.currentIndexChanged.connect( Slots.change_max_spinbox_commission)
def run_simulation(self, mode_debug=False): """ Start simulation :param mode_debug: if want print the logs :type mode_debug: bool :return: None """ # As long as there is a new business day in our simulation; trading = True while trading: # Sell companies in our portfolio that satisfy our criteria for selling; self._sell() # If we have enough money, buy companies trading this day that satisfy our criteria for buying; if self._portfolio.can_buy(): self._buy() # Keep track of our assets self._tracking(mode_debug=mode_debug) # Go to the next trading day. trading = self._market.next() # Update plot QT if self._fig: # Calculate portfolio_value with ref_curve for ref_curve optimal HelperFunctionQt.update_plot( self._fig, sorted(self._hist_market_value.keys()), self._simulation_port_value, self._ref_curve_value) self._fig.savefig( self.log_broker.name.replace('log_brok', 'simulation')[:-3] + 'png', format='png') if mode_debug: self._portfolio.print_portfolio()
def add_company_to_portfolio_stock_screener(): """ Get all information to add companies in portfolio with call function HelperFunctionQt.add_companies_to_portfolio_db :return: None """ table_widget = ui.tableWidget_stockScreener if table_widget.rowCount() > 0: list_company = [] for idx in range(table_widget.rowCount()): # get checkbox widget cb = HelperFunctionQt.get_widget_of_layout( table_widget.cellWidget(idx, table_widget.columnCount() - 1).layout(), QtGui.QCheckBox) if cb.isChecked(): # add symbol company in list company to add in DB for a portfolio list_company.append(table_widget.item(idx, 1).text()) # get name portfolio portfolio_name = ui.comboBox_stockScreener_portfolio.lineEdit( ).text() # add company to portfolio in db HelperFunctionQt.add_companies_to_portfolio_db( portfolio_name, list_company, db) # Refresh combo box if is new if ui.comboBox_stockScreener_portfolio.findText( portfolio_name) == -1: ui.comboBox_stockScreener_portfolio.addItem(portfolio_name)
def deselect_all_criteria_simulator(): """ Deselect all criteria of stock screener :return: None """ HelperFunctionQt.select_deselect_combobox_layout( ui.verticalLayout_left_2, QtCore.Qt.Unchecked) HelperFunctionQt.select_deselect_combobox_layout( ui.verticalLayout_right_2, QtCore.Qt.Unchecked)
def select_all_criteria_stock_screener(): """ Select all criteria of stock screener :return: None """ HelperFunctionQt.select_deselect_combobox_layout( ui.verticalLayout_left, QtCore.Qt.Checked) HelperFunctionQt.select_deselect_combobox_layout( ui.verticalLayout_right, QtCore.Qt.Checked)
def sort_column_checkbox_table_widget_portfolio_manager(column): """ Sorted column with checkbox, ascending = Unchecked to Checked ; descending = Checked to Unchecked :param column: column of header cell clicked :type column: int :return: None """ if column == ui.tableWidget_portfolio.columnCount() - 1: HelperFunctionQt.sorted_column_checkbox_table_widget( ui.tableWidget_portfolio)
def refresh_data_table_portfolio(self): """ Refresh data of table portfolio depending on portfolio chosen :return: None """ list_column_table = ['name', 'symbol'] # get name portfolio self.tableWidget_portfolio.setRowCount(0) portfolio_name = self.comboBox_portfolioManager_portfolio.lineEdit( ).text() if portfolio_name == '' or portfolio_name is None: self.frame_managerPortfolio.setEnabled(False) # self.tableWidget_portfolio.clearContents() return 0 # no portfolio name else: # Refresh combo box if is new if ui.comboBox_portfolioManager_portfolio.findText( portfolio_name) == -1: ui.comboBox_portfolioManager_portfolio.addItem(portfolio_name) self.frame_managerPortfolio.setEnabled(True) # add portfolio if is new portfolio_id = ManagerPortfolio.create_portfolio( portfolio_name, db)[0].get('id_portfolio')[0] self.lineEdit_noPortfolio.setText( str(portfolio_id)) # set id portfolio to line edit list_company = ManagerPortfolio.get_companies_to_portfolio( portfolio_id, db) if self.tableWidget_portfolio.rowCount() < len(list_company): self.tableWidget_portfolio.setRowCount(len(list_company)) sorting_enable = self.tableWidget_portfolio.isSortingEnabled() self.tableWidget_portfolio.setSortingEnabled(False) for idx_row, company in enumerate(list_company): for key in company.keys(): try: idx_column = list_column_table.index(key) assert (idx_column > 0 or idx_column < self.tableWidget_portfolio.rowCount()), \ 'Problem index of column when insert new row' # create new cell HelperFunctionQt.create_new_cell_item_table_widget( self.tableWidget_portfolio, idx_row, idx_column, company.get(key)) except ValueError: continue # if column no exists in table stock screener, we continue # create cell with checkbox in last column cb = QtGui.QCheckBox() HelperFunctionQt.create_new_cell_widget_table_widget( self.tableWidget_portfolio, idx_row, self.tableWidget_portfolio.columnCount() - 1, cb) self.tableWidget_portfolio.setSortingEnabled(sorting_enable)
def add_company_to_portfolio_portfolio_manager(): """ Add company selected to portfolio selected with call function HelperFunctionQt.add_companies_to_portfolio_db :return: None """ company = ui.comboBox_portfolioManager_addCompany.lineEdit().text( ).split() # get name portfolio portfolio_name = ui.comboBox_portfolioManager_portfolio.lineEdit( ).text() # add company to portfolio in db HelperFunctionQt.add_companies_to_portfolio_db(portfolio_name, [company[0]], db) # refresh table portfolio manager ui.refresh_data_table_portfolio()
def sort_column_checkbox_table_widget_stock_screener(column): """ Sorted column with checkbox, ascending = Unchecked to Checked ; descending = Checked to Unchecked :param column: column of header cell clicked :type column: int :return: None """ table_widget = ui.tableWidget_stockScreener # When a click is made on a column's name, a sorting is done. We are changing the indicator in MainWindow # accordingly. The ValueTableItems that we are using use that indicator to adjust their comparison's algorithms. if table_widget.horizontalHeader().sortIndicatorOrder() == 0: Singleton.set_order(Singleton(), True) else: Singleton.set_order(Singleton(), False) if column == table_widget.columnCount() - 1: HelperFunctionQt.sorted_column_checkbox_table_widget(table_widget)
def deleted_company_selected_table_portfolio(): table_widget = ui.tableWidget_portfolio if table_widget.rowCount() > 0: list_company_deleted = [] for idx in range(table_widget.rowCount()): # get checkbox widget cb = HelperFunctionQt.get_widget_of_layout( table_widget.cellWidget(idx, table_widget.columnCount() - 1).layout(), QtGui.QCheckBox) if cb.isChecked(): # add symbol company in list company to delete in DB for a portfolio list_company_deleted.append( table_widget.item(idx, 1).text()) # get name portfolio portfolio_id = ui.lineEdit_noPortfolio.text() # add company to portfolio in db HelperFunctionQt.delete_companies_to_portfolio_db( portfolio_id, list_company_deleted, db) # refresh table portfolio ui.refresh_data_table_portfolio()
def get_all_min_max_criteria(horizontal_layout): """ Get all min and max checked in layout horizontal criteria who content vertical layout left and right for tab Stock Screener or Portfolio Manager :param horizontal_layout: layout horizontal criteria who content vertical layout left and right :type horizontal_layout: QtGui.QBoxLayout :return: dict of criteria checked :rtype: dict{dict} """ dict_min_max = {} # layout left layout = HelperFunctionQt.get_widget_of_layout(horizontal_layout, QtGui.QLayout) dict_min_max.update( HelperFunctionQt.get_min_max_layout_checked(layout)) # layout right layout = HelperFunctionQt.get_widget_of_layout(horizontal_layout, QtGui.QLayout, 1) dict_min_max.update( HelperFunctionQt.get_min_max_layout_checked(layout)) return dict_min_max
def connection_interface_stock_screener(self): """ Connection signal-slot in interface Stock Screener :return: None """ # sort column checkbox of table stock screener self.tableWidget_stockScreener.horizontalHeader().sectionClicked \ .connect(Slots.sort_column_checkbox_table_widget_stock_screener) # checked or unchecked the checkbox of cell clicked self.tableWidget_stockScreener.cellClicked.connect( Slots.modify_checkbox_table_widget_stock_screener) # connection btn Add to portfolio of Stock Screener self.btn_stockScreener_addPortfolio.clicked.connect( Slots.add_company_to_portfolio_stock_screener) # connection combo box line edit to portfolio of Stock Screener to same fct of btn Add to portfolio self.comboBox_stockScreener_portfolio.lineEdit().returnPressed \ .connect(Slots.add_company_to_portfolio_stock_screener) # link slider and spin box of box layout to left HelperFunctionQt.link_spin_slider_layout(self.verticalLayout_left) # link slider and spin box of box layout to right HelperFunctionQt.link_spin_slider_layout(self.verticalLayout_right) # btn select criteria stock sceenner self.btn_selectAllCriteria.clicked.connect( Slots.select_all_criteria_stock_screener) # btn deselect criteria stock sceenner self.btn_deselectAllCriteria.clicked.connect( Slots.deselect_all_criteria_stock_screener) # connection btn Add to portfolio of Portfolio Manager self.btn_addCompany.clicked.connect( Slots.add_company_to_portfolio_portfolio_manager) # connection combo box line edit to portfolio of Portfolio Manager to same fct of btn Add to portfolio self.comboBox_portfolioManager_addCompany.lineEdit().returnPressed \ .connect(Slots.add_company_to_portfolio_portfolio_manager) # Refresh table and global ranking depending on criteria selected self.btn_RefreshTableStockScreener.clicked.connect( Slots.refresh_table_stock_screener)
def setup_manager(self): """ Setup for widget already in MainWindow.ui to modify :return: None """ # create folder for results simulation if not exists if not os.path.exists( path_log_broker[:path_log_broker.rfind('/') + 1]): os.makedirs(path_log_broker[:path_log_broker.rfind('/') + 1]) self.get_min_max_value_criteria() # Stock Screener # Set min max criteria Stock Screener HelperFunctionQt.set_min_max_slider_layout( self.verticalLayout_left, dict_min_max_value_criteria) HelperFunctionQt.set_min_max_slider_layout( self.verticalLayout_right, dict_min_max_value_criteria) self.create_data_table_stock_screener() # Add placeholder to combobox portfolio Stock screener self.comboBox_stockScreener_portfolio.lineEdit().setPlaceholderText( "Choose your portfolio name.") self.create_combobox_portfolio('tab_stockScreener', 'comboBox_stockScreener_portfolio') # Portfolio Manager self.comboBox_portfolioManager_portfolio.lineEdit().setPlaceholderText( "Choose your portfolio name.") self.create_combobox_portfolio('tab_portfolioManager', 'comboBox_portfolioManager_portfolio') if self.comboBox_portfolioManager_portfolio.count() > 0: self.refresh_data_table_portfolio() self.create_combobox_company_portfolio_manager() # Simulator # Set min max criteria Simulator HelperFunctionQt.set_min_max_slider_layout( self.verticalLayout_left_2, dict_min_max_value_criteria) HelperFunctionQt.set_min_max_slider_layout( self.verticalLayout_right_2, dict_min_max_value_criteria) # Set min max datetime Simulator self.get_min_max_date_historic() # Add items of combobox type_simulation who be in list_type_simulation self.comboBox_typeSimulation.addItems( sorted(list(dict_type_simulation.keys()))) # Set display format date, bu in Linux self.dateEdit_simulatorFrom.setDisplayFormat('yyyy-MM-dd') self.dateEdit_simulatorTo.setDisplayFormat('yyyy-MM-dd')
def open_windows_setting_params_simulation(): """ Open pop-up of dialog Qt to set params specific to type simulation selected. The value of params is keeping in dict_params_value_sim, dict global :return: None """ type_simulation_selected = ui.comboBox_typeSimulation.currentText() print(type_simulation_selected) # TODO: open dynamically a pop-up for a specific type simulation Dialog = QtGui.QDialog() dl = Ui_Dialog() dl.setupUi(Dialog) # Set pop-up params of type simulation if reopen pop-up with same type simulation if len(dict_params_value_sim) > 0: for child in Dialog.children(): name_obj = child.objectName() if isinstance(child, QtGui.QDialogButtonBox) or isinstance( child, QtGui.QLabel): continue elif dict_params_value_sim.get(name_obj[name_obj.rfind('_') + 1:]) is not None: if isinstance(child, QtGui.QComboBox): idx_cb = child.findText( dict_params_value_sim.get( name_obj[name_obj.rfind('_') + 1:])) child.setCurrentIndex(idx_cb) elif isinstance(child, (QtGui.QDoubleSpinBox, QtGui.QSpinBox)): child.setValue( dict_params_value_sim.get( name_obj[name_obj.rfind('_') + 1:])) else: child.setEditText( dict_params_value_sim.get( name_obj[name_obj.rfind('_') + 1:])) if Dialog.exec(): dict_params_value_sim.update( HelperFunctionQt.get_params_simulation(Dialog)) print(dict_params_value_sim)
def create_data_table_stock_screener(self): """ Create data in table widget stock screener with data SQL :return: None """ list_column_table = [ 'company_name', 'symbol', 'Revenue (Mil)', 'Net Income (Mil)', 'Gross Margin (%)', 'Dividends', 'Div. Yield (%)', 'EPS', 'P/E Ratio', 'BVPS', 'P/B Ratio', 'FCFPS', 'Adj. Close', '52wk (%)', 'Global Ranking' ] dict_company = ManagerCompany.get_historic_value_all_company(db) dict_params = self.get_all_min_max_criteria(self.horizontalLayout) max_nb_company = len(dict_company) dict_company = HelperFunctionQt.reduce_table(dict_company, dict_params) dict_company = HelperFunctionQt.calculate_global_ranking( dict_company, dict_params) self.lineEdit_nb_company.setText( '%s/%s' % (str(len(dict_company)), str(max_nb_company))) if self.tableWidget_stockScreener.rowCount() < len(dict_company): self.tableWidget_stockScreener.setRowCount(len(dict_company)) sorting_enable = self.tableWidget_stockScreener.isSortingEnabled() self.tableWidget_stockScreener.setSortingEnabled(False) for idx_row, company in enumerate(dict_company): for key in company.keys(): try: idx_column = list_column_table.index(key) assert (idx_column > 0 or idx_column < self.tableWidget_stockScreener.rowCount()), \ 'Problem index of column when insert new row' # create new cell HelperFunctionQt.create_new_cell_item_table_widget( self.tableWidget_stockScreener, idx_row, idx_column, company.get(key)) except ValueError: continue # if column no exists in table stock screener, we continue # create cell with checkbox in last column cb = QtGui.QCheckBox() HelperFunctionQt.create_new_cell_widget_table_widget( self.tableWidget_stockScreener, idx_row, self.tableWidget_stockScreener.columnCount() - 1, cb) self.tableWidget_stockScreener.setSortingEnabled(sorting_enable)
def start_simulation(): print('Start simulation') dict_params_simulation = HelperFunctionQt.get_params_simulation( ui.frame_simulation) dict_params_simulation.update(dict_params_value_sim) print(dict_params_simulation) dict_min_max = {} dict_min_max.update( HelperFunctionQt.get_min_max_layout_checked( ui.verticalLayout_left_2)) dict_min_max.update( HelperFunctionQt.get_min_max_layout_checked( ui.verticalLayout_right_2)) print(dict_min_max) fig = HelperFunctionQt.create_plot_qt([], [], [], ui.horizontalLayout_plot) str_timestamp = str(int(datetime.timestamp(datetime.now()))) broker = Broker( db, dict_params_simulation['valuePortfolio'], path_log_broker.replace('log_brok', 'log_brok_' + str_timestamp), path_log_broker_ref, path_log_port.replace('log_port', 'log_port_' + str_timestamp), datetime.strptime(dict_params_simulation['simulatorFrom'], '%Y-%m-%d'), datetime.strptime(dict_params_simulation['simulatorTo'], '%Y-%m-%d'), dict_params_simulation.get('minInvest', 0), dict_params_simulation.get('maxInvest', MAX_INT), fig) # Keep params to simulation in a log file_log_params = open( path_log_broker.replace('log_brok', 'log_params_sim_' + str_timestamp), 'w') file_log_params.write(str(dict_params_simulation) + '\n') file_log_params.write(str(dict_min_max) + '\n') file_log_params.close() # set type and value commission if dict_params_simulation['commissionPctDollar'] == '%': broker.set_percent_commission( dict_params_simulation.get('commission', 0)) elif dict_params_simulation['commissionPctDollar'] == '$': broker.set_flat_fee_commission( dict_params_simulation.get('commission', 0)) else: raise ValueError( 'Error type commission, % or $, you put %s' % str(dict_params_simulation['commissionPctDollar'])) # Add filter for criteria selected for criterion, min_max in dict_min_max.items(): name_bd_criterion = HelperFunctionQt.dict_criteria.get(criterion) if not name_bd_criterion: print( 'Error criterion name, not exists in dictionary of HelperFunctionQt.dict_criteria, criterion = %s' % criterion) broker.add_sell_filters( Filters.FilterCriteriaMinMaxSell(name_bd_criterion, min_max.get('min', 0), min_max.get('max', 0))) broker.add_buy_filters( Filters.FilterCriteriaMinMaxBuy(name_bd_criterion, min_max.get('min', 0), min_max.get('max', 0))) # Configure simulation predefined in dict_params_simulation if dict_type_simulation.get(ui.comboBox_typeSimulation.currentText() ) == '1_stock_for_each_company': broker.add_max_nb_of_stocks_to_buy(1) broker.add_sell_filters(Filters.FilterNot()) broker.add_buy_filters(Filters.FilterNotInPortfolio()) # no type simulation specific elif dict_type_simulation.get( ui.comboBox_typeSimulation.currentText()) == 'global_ranking': if len(dict_min_max) < 1: dict_min_max = HelperFunctionQt.dict_criteria broker.add_sell_filters(Filters.FilterCriteriaGlobalRankingSell()) broker.add_buy_filters(Filters.FilterCriteriaGlobalRankingBuy()) broker.calculate_global_ranking(True, dict_min_max) elif dict_type_simulation.get( ui.comboBox_typeSimulation.currentText()) == '': pass else: raise ValueError( 'Error type simulation, it\'s not in list, you put %s' % ui.comboBox_typeSimulation.currentText()) broker.run_simulation() print('End of simulation')
def __init__(self, db, initial_liquidity, log_broker, log_broker_ref, log_port, min_date=datetime(2006, 1, 3), max_date=datetime(2016, 11, 4), min_value=0, max_value=float("inf"), fig=None): """ Create Broker :param db: connexion in to DB :type db: Manager_DB.DbConnection.DbConnection :param initial_liquidity: value to portfolio to begin :type initial_liquidity: int :param log_broker: path file to write log of Broker :type log_broker: str :param log_broker_ref: path file to write log of Broker ref_curve :type log_broker_ref: str :param log_port: path file to write log of Portfolio :type log_port: str :param min_date: date to start simulation :type min_date: datetime.datetime :param max_date: date included when the simulation stops :type max_date: datetime.datetime :param min_value: min stock value to do transaction :type min_value: int :param max_value: max stock value to invest in a company :type max_value: int :param fig: figure for update plot QT :type fig: matplotlib.figure.Figure """ # The Market where the broker is buying and selling stocks self._market = Market(min_date, max_date, db) self.log_broker = open(log_broker, 'w') self.log_broker.write( "date;cash;stocks_value;bill;value_with_ref_curve\n") # The portfolio contains all the stocks bought for the current day and time and # the cash money that can be used instantly by the broker to buy stocks. self._portfolio = Portfolio(initial_liquidity, min_value, max_value, log_port) # The bill is how much the broker has charged for its services. self._bill = 0.0 # Dictionary that keeps track of the value of our portfolio at any given time since the start of the simulation. # Key: Date ; Value: Total of our assets for any given self._hist_market_value = {} self._simulation_port_value = [] # keep in memory value in order dates # A commission is how much the broker is asking to get paid for a given transaction. # Initially, there is no commission. It must be added with a setter. self._commission = self._Commission() # Filters are functions used to select which companies should be in our portfolio at any given time. self._sell_filters = [] self._buy_filters = [] self._fig = fig self._data_ref_curve = HelperFunctionQt.read_reference_curve( log_broker_ref, True) self._ref_curve_value = []