class SDownload(BoxLayout): account_id = ObjectProperty(None) stock_id = ObjectProperty(None) datatypebtn_id = ObjectProperty(None) startdate_id = ObjectProperty(None) totaldays_id = ObjectProperty(None) datestr_id = ObjectProperty(None) closebtn_id = ObjectProperty(None) dataType = "m" userConf = sutil.getDictFromFile( os.path.join(os.path.dirname(__file__), ".." + os.sep + "conf" + os.sep + "user.ini")) def datatypeSelect(self, instance, atext): self.datatypebtn_id.text = atext if atext == "月線": self.totaldays_id.text = "全部" self.totaldays_id.disabled = False self.datestr_id.text = "月" self.dataType = "m" elif atext == "週線": self.totaldays_id.text = "全部" self.totaldays_id.disabled = False self.datestr_id.text = "週" self.dataType = "w" elif atext == "日線": self.totaldays_id.text = "90" self.totaldays_id.disabled = False self.datestr_id.text = "天" self.dataType = "d" elif atext == "tick線": self.totaldays_id.text = "1" self.totaldays_id.disabled = True self.datestr_id.text = "天" self.dataType = "0" else: self.totaldays_id.text = "5" self.totaldays_id.disabled = False self.datestr_id.text = "天" index = atext.find("分線") self.dataType = atext[0:index] def __init__(self, paramDict, **kwargs): super(SDownload, self).__init__(**kwargs) self.paramDict = paramDict self.app = self.paramDict.get(CONSTS.S_APP) self.datatype_dropdown = DatatypeDropDown() self.datatypebtn_id.bind(on_release=self.datatype_dropdown.open) self.datatype_dropdown.bind(on_select=self.datatypeSelect) self.accountIDDropDown = SAccountIDDropDown() firstRecord = True accountIdList = self.app.accountIdList for astr in accountIdList: if firstRecord == True: firstRecord = False self.account_id.text = astr abtn = SButton(text=astr) abtn.size_hint_y = None abtn.height = 30 abtn.bind(on_release=self.accountIDDropDown.select) self.accountIDDropDown.add_widget(abtn) self.account_id.bind(on_release=self.accountIDDropDown.open) self.accountIDDropDown.bind(on_select=self.accountSelect) self.startdate_id.bind(focus=self.onFocus) self.initial_data() def accountSelect(self, instance, atext): self.account_id.text = atext.text def onFocus(self, instance, value): if value: content = BoxLayout(size_hint=(1, 1), orientation="vertical") self.datePicker = SDatePicker(self.startdate_id.text) self.datePicker.size_hint = (1, .8) content.add_widget(self.datePicker) bottomLayout = BoxLayout(size_hint=(1, .1), orientation="horizontal") ensurebtn = SButton(text="確定", size_hint=(.49, .8)) bottomLayout.add_widget(ensurebtn) bottomLayout.add_widget(BoxLayout(size_hint=(.02, 1))) closebtn = SButton(text="關閉", size_hint=(.49, .8)) bottomLayout.add_widget(closebtn) content.add_widget(bottomLayout) self._popup = SPopup(title="日期選擇", content=content, title_font=CONSTS.FONT_NAME, size_hint=(None, None), size=(250, 330), auto_dismiss=False) ensurebtn.bind(on_press=self.datePickerEvent) closebtn.bind(on_press=self._popup.dismiss) self._popup.open() def datePickerEvent(self, instance): self.startdate_id.text = self.datePicker.date_text self._popup.dismiss() def initial_data(self): self.startdate_id.text = str( sdate_utils.getPrevDate(sdate_utils.getCurrentDate())) self.totaldays_id.text = "全部" def downloadData(self): useridTxt = self.account_id.text if useridTxt == "": self.app.showErrorView(True, CONSTS.ERR_USER_IS_SPACE) return stockidTxt = self.stock_id.text if stockidTxt == "": self.app.showErrorView(True, CONSTS.ERR_STOCKID_IS_SPACE) return if useridTxt.find("@") != -1: useridTxt = "1|" + useridTxt else: useridTxt = "2|" + useridTxt gwParam = {} gwParam["Host"] = self.userConf.get("DOWNLOAD_URL").strip() gwParam["Port"] = int(self.userConf.get("DOWNLOAD_PORT").strip()) gwParam["User"] = useridTxt gwParam["Password"] = self.app.pwd gwParam["ProductId"] = int(self.userConf.get("PRODUCT_ID").strip()) gwParam["UserType"] = int(self.userConf.get("USER_TYPE").strip()) gwParam["LoginType"] = int( self.userConf.get("TRADE_LOGIN_TYPE").strip()) exchange = "ZZ" gwParam["StockFullID"] = exchange + stockidTxt gwParam["DataType"] = self.dataType startDate = self.startdate_id.text if self.dataType == "m" or self.dataType == "w": startDate = "0" gwParam["StartDate"] = startDate totalDaysStr = self.totaldays_id.text if totalDaysStr == "全部": totalDays = "0" else: totalDays = totalDaysStr if self.dataType != "m" and self.dataType != "w" and self.dataType != "d": if int(totalDays) > 5: totalDays = "5" self.totaldays_id.text = "5" gwParam["DataDays"] = totalDays sysConfDict = self.app.confDict.get(CONSTS.SYS_CONF_DICT) refParam = {} refParam["CONSTS.S_APP"] = self.app refParam["TitleMsg"] = sysConfDict.get("MSG_TITLE") refParam["InfoMsg"] = " 資料下載中..." refParam["PopupSize"] = (160, 120) refParam["GwParam"] = gwParam refParam["GwFunc"] = abxtoolkit.request_rowdata refParam["ResultFunc"] = self._finishedDownload sgwPopup = SGwPopup(refParam) sgwPopup.processEvent() def _finishedDownload(self, gwResult): fileName = gwResult.get("FileName") fileLen = gwResult.get("FileLen") content = BoxLayout(size_hint=(1, 1), orientation="vertical") content.add_widget(BoxLayout(size_hint=(1, .05))) fileLayout = GridLayout(cols=2, spacing=2, size_hint=(1, None)) fileLayout.bind(minimum_height=fileLayout.setter('height')) fileLayout.add_widget( SLabel(text="檔案目錄:", size_hint=(.22, None), height=30)) fileLayout.add_widget( SLabel(text=download_path, size_hint=(.78, None), height=30)) fileLayout.add_widget( SLabel(text="檔案名稱:", size_hint=(.22, None), height=30)) fileLayout.add_widget( SLabel(text=fileName, size_hint=(.78, None), height=30)) fileLayout.add_widget( SLabel(text="檔案長度:", size_hint=(.22, None), height=30)) fileLayout.add_widget( SLabel(text=str(fileLen), size_hint=(.78, None), height=30)) content.add_widget(fileLayout) content.add_widget(BoxLayout(size_hint=(1, .05))) bottomLayout = BoxLayout(size_hint=(1, .1), orientation="horizontal") ensurebtn = SButton(text="確定", size_hint=(1, .8)) bottomLayout.add_widget(ensurebtn) content.add_widget(bottomLayout) self.fin_popup = Popup(title="下載完成", content=content, title_font=CONSTS.FONT_NAME, size_hint=(None, None), size=(360, 200), auto_dismiss=False) ensurebtn.bind(on_press=self.fin_popup.dismiss) self.fin_popup.open() def showExplain(self): filePath = os.path.join(os.path.dirname(__file__), "../conf/explain.ini") with open(filePath, 'r', encoding='utf-8-sig') as f: lineList = f.readlines() explainStr = "" for astr in lineList: explainStr += astr contentLayout = STableBoxLayout(size_hint=(1, 1), orientation="vertical") slview = STableScrollView(size_hint=(1, .92)) contentLayout.add_widget(slview) explainLayout = STableBoxLayout(size_hint=(1, None)) explainLayout.bind(minimum_height=explainLayout.setter('height')) explainLabel = SLabel(text=explainStr, size_hint=(1, None)) explainLabel.font_name = CONSTS.FONT_NAME explainLabel.color = colorHex("#000000") explainLayout.add_widget(explainLabel) slview.add_widget(explainLayout) bottomLayout = BoxLayout(size_hint=(1, .08)) closebtn_id = SButton(text="關閉", size_hint=(1, .8)) bottomLayout.add_widget(closebtn_id) contentLayout.add_widget(bottomLayout) popup = SPopup(title="股票代碼說明", content=contentLayout, size_hint=(None, None), size=(500, 400), auto_dismiss=False) closebtn_id.bind(on_press=popup.dismiss) popup.title_font = CONSTS.FONT_NAME popup.open()
class STradeCost(BoxLayout): def __init__(self, paramDict, **kwargs): super(STradeCost, self).__init__(**kwargs) self.paramDict = paramDict self.app = self.paramDict.get(CONSTS.S_APP) self.size_hint = (1, 1) self.orientation = "vertical" headLayout = STableGridLayout(cols=4, rows=1, spacing=2, size_hint=(1, None), height=30) headLabel = SHeadLabel(text="功能", size_hint=(.15, 1)) headLabel.halign: 'center' headLabel.valign: 'middle' headLayout.add_widget(headLabel) headLabel = SHeadLabel(text="規則", size_hint=(.4, 1)) headLabel.halign: 'center' headLabel.valign: 'middle' headLayout.add_widget(headLabel) headLabel = SHeadLabel(text="交易單位/契約乘數", size_hint=(.25, 1)) headLabel.halign: 'center' headLabel.valign: 'middle' headLayout.add_widget(headLabel) headLabel = SHeadLabel(text="手續費+交易稅", size_hint=(.2, 1)) headLabel.halign: 'center' headLabel.valign: 'middle' headLayout.add_widget(headLabel) self.add_widget(headLayout) gapLayout = STableBoxLayout(size_hint=(1, None), height=2) self.add_widget(gapLayout) self.maxIndex = 0 self.def_ids = {} slview = STableScrollView() slview.size_hint = (1, None) slview.size = (540, 350) self.contentLayout = STableGridLayout(cols=4, spacing=2, size_hint_y=None) # Make sure the height is such that there is something to scroll. self.contentLayout.bind( minimum_height=self.contentLayout.setter('height')) filePath = os.path.join( os.path.dirname(__file__), ".." + os.sep + "conf" + os.sep + "tradecost.ini") if not os.path.exists(filePath): with open(filePath, 'w'): pass alist = sutil.getListFromFile(filePath) for astr in alist: tmpList = astr.strip().split(",") if len(tmpList) < 3: continue self.addListRow(tmpList, False) self.maxIndex += 1 self.addInsertRow(str(self.maxIndex)) slview.add_widget(self.contentLayout) self.add_widget(slview) closeLayout = BoxLayout(size_hint=(1, None), height=36) self.closebtn_id = SButton(text="關閉", size_hint=(1, 1)) closeLayout.add_widget(self.closebtn_id) self.add_widget(closeLayout) def addListRow(self, alist, aflag): if aflag: self.deleteRow(self.maxIndex) rowList = [] funcLayout = SBoxLayout(size_hint=(.15, None), height=30) funcLayout.orientation = "horizontal" funcLayout.padding = (1, 1, 1, 1) funcLayout.add_widget(BoxLayout(size_hint=(.09, 1))) btn = SInfoButton(extra_info=self.maxIndex, text="修", size_hint=(.4, 1)) btn.halign = "center" btn.valign = "middle" btn.bind(on_release=self.updateRecordPopup) funcLayout.add_widget(btn) funcLayout.add_widget(BoxLayout(size_hint=(.02, 1))) btn = SInfoButton(extra_info=self.maxIndex, text="刪", size_hint=(.4, 1)) btn.halign = "center" btn.valign = "middle" btn.bind(on_release=self.deleteRecordPopup) if alist[0] == "證券普通股" or alist[0] == "台指期貨": btn.disabled = True funcLayout.add_widget(btn) funcLayout.add_widget(BoxLayout(size_hint=(.09, 1))) rowList.append(funcLayout) self.contentLayout.add_widget(funcLayout) contentLabel = SContentLabel(text=alist[0], size_hint=(.4, None), height=30) contentLabel.color = colorHex("#000000") contentLabel.halign = "left" contentLabel.valign = "middle" rowList.append(contentLabel) self.contentLayout.add_widget(contentLabel) contentLabel = SContentLabel(text=alist[1], size_hint=(.25, None), height=30) contentLabel.color = colorHex("#000000") contentLabel.halign = "right" contentLabel.valign = "middle" rowList.append(contentLabel) self.contentLayout.add_widget(contentLabel) contentLabel = SContentLabel(text=alist[2], size_hint=(.2, None), height=30) contentLabel.color = colorHex("#000000") contentLabel.halign = "right" contentLabel.valign = "middle" rowList.append(contentLabel) self.contentLayout.add_widget(contentLabel) self.def_ids[self.maxIndex] = rowList def deleteRow(self, rowIndex): rowList = self.def_ids.get(rowIndex) for obj in rowList: self.contentLayout.remove_widget(obj) self.def_ids.pop(rowIndex) self.saveData() def saveData(self): keylist = self.def_ids.keys() keylist = sorted(keylist) listLen = len(keylist) filePath = os.path.join( os.path.dirname(__file__), ".." + os.sep + "conf" + os.sep + "tradecost.ini") with open(filePath, 'w', encoding='utf-8') as f: rowList = None for i in range(0, listLen - 1): rowList = self.def_ids.get(keylist[i]) astr = rowList[1].text + "," + rowList[2].text + "," + rowList[ 3].text + "\n" f.write(astr) def addInsertRow(self, strIndex): rowList = [] funcLayout = SBoxLayout(size_hint=(.15, None), height=30) funcLayout.orientation = "horizontal" funcLayout.padding = (1, 1, 1, 1) funcLayout.add_widget(BoxLayout(size_hint=(.1, 1))) btn = SButton(text="新增", size_hint=(.8, 1)) btn.halign = "center" btn.valign = "middle" btn.bind(on_release=self.addRecordPopup) funcLayout.add_widget(btn) funcLayout.add_widget(BoxLayout(size_hint=(.1, 1))) rowList.append(funcLayout) self.contentLayout.add_widget(funcLayout) contentLabel = SContentLabel(text="", size_hint=(.4, None), height=30) contentLabel.halign = "left" contentLabel.valign = "middle" rowList.append(contentLabel) self.contentLayout.add_widget(contentLabel) contentLabel = SContentLabel(text="", size_hint=(.25, None), height=30) contentLabel.halign = "right" contentLabel.valign = "middle" rowList.append(contentLabel) self.contentLayout.add_widget(contentLabel) contentLabel = SContentLabel(text="", size_hint=(.2, None), height=30) contentLabel.halign = "right" contentLabel.valign = "middle" rowList.append(contentLabel) self.contentLayout.add_widget(contentLabel) self.def_ids[int(strIndex)] = rowList def addRecordPopup(self, instance): refDict = {} for key in self.paramDict.keys(): refDict[key] = self.paramDict.get(key) refDict['mode'] = "1" self.add_scsLayout = SCostSetting(refDict) self.add_popup = SPopup(title="新增規則", content=self.add_scsLayout, size_hint=(None, None), size=(480, 360), auto_dismiss=False) self.add_scsLayout.ensurebtn_id.bind(on_press=self.addRecordEvent) self.add_scsLayout.closebtn_id.bind(on_press=self.add_popup.dismiss) self.add_popup.title_font = CONSTS.FONT_NAME self.add_popup.open() def addRecordEvent(self, instance): ruleName = self.add_scsLayout.rule_id.text if ruleName == None or ruleName == "": self.app.showErrorView(True, CONSTS.ERR_RULE_IS_SPACE) return costStr = self.add_scsLayout.cost_id.text if costStr == None or costStr == "": self.app.showErrorView(True, CONSTS.ERR_COST_IS_SPACE) return dflag = False try: float(costStr) except: dflag = True if dflag: self.app.showErrorView(True, CONSTS.ERR_COST_MUST_NUMBER) return dflag = False for akey in self.def_ids.keys(): rowList = self.def_ids.get(akey) if ruleName == rowList[1].text: dflag = True break if dflag: self.app.showErrorView(True, CONSTS.ERR_RULE_DUPLICATED) return tradeUnit = self.add_scsLayout.tradeunit_id.text alist = [] alist.append(ruleName) alist.append(tradeUnit) alist.append(costStr) self.addListRow(alist, True) self.maxIndex += 1 self.addInsertRow(str(self.maxIndex)) self.saveData() self.add_popup.dismiss() def updateRecordPopup(self, instance): refDict = {} for key in self.paramDict.keys(): refDict[key] = self.paramDict.get(key) refDict['mode'] = "2" self.update_scsLayout = SCostSetting(refDict) self.update_popup = SPopup(title="修改規則", content=self.update_scsLayout, size_hint=(None, None), size=(480, 360), auto_dismiss=False) self.update_scsLayout.ensurebtn_id.extra_info = instance.extra_info self.update_scsLayout.ensurebtn_id.bind( on_press=self.updateRecordEvent) self.update_scsLayout.closebtn_id.bind( on_press=self.update_popup.dismiss) self.update_popup.title_font = CONSTS.FONT_NAME rowList = self.def_ids.get(instance.extra_info) self.update_scsLayout.rule_id.text = rowList[1].text self.update_scsLayout.tradeunit_id.text = rowList[2].text self.update_scsLayout.cost_id.text = rowList[3].text if self.update_scsLayout.rule_id.text == "證券普通股" or self.update_scsLayout.rule_id.text == "台指期貨": self.update_scsLayout.tradeunit_id.disabled = True self.update_popup.open() def updateRecordEvent(self, instance): costStr = self.update_scsLayout.cost_id.text if costStr == None or costStr == "": self.app.showErrorView(True, CONSTS.ERR_COST_IS_SPACE) return dflag = False try: float(costStr) except: dflag = True if dflag: self.app.showErrorView(True, CONSTS.ERR_COST_MUST_NUMBER) return tradeUnit = self.update_scsLayout.tradeunit_id.text rowList = self.def_ids.get(instance.extra_info) rowList[2].text = tradeUnit rowList[3].text = costStr self.saveData() self.update_popup.dismiss() def deleteRecordPopup(self, instance): self.deleteConfirm = SRowConfirmLayout() self.del_popup = SPopup(title="刪除規則", content=self.deleteConfirm, size_hint=(None, None), size=(240, 160), auto_dismiss=False) self.deleteConfirm.yesbtn_id.extra_info = instance.extra_info self.deleteConfirm.yesbtn_id.bind(on_press=self.deleteRecordEvent) self.deleteConfirm.nobtn_id.bind(on_press=self.del_popup.dismiss) self.del_popup.title_font = CONSTS.FONT_NAME self.del_popup.open() def deleteRecordEvent(self, instance): self.deleteRow(instance.extra_info) self.del_popup.dismiss()
class SelfStkSetting(BoxLayout): def __init__(self, paramDict, **kwargs): super(SelfStkSetting, self).__init__(**kwargs) self.paramDict = paramDict self.app = self.paramDict.get(CONSTS.S_APP) self.selfgroup_index = self.paramDict.get("SelfGroupIndex") self.selfgroup_name = self.paramDict.get("SelfGroupName") self.selfStkList = self.paramDict.get("SelfStkList") self.size_hint = (1, 1) self.orientation = "vertical" self.add_widget(STableBoxLayout(size_hint=(1, None), height=1)) nameLayout = SBoxLayout(size_hint=(1, None), height=30) nameLayout.orientation = "horizontal" nameLayout.add_widget(STableBoxLayout(size_hint=(.02, 1))) nameLabel = SLabel(text="名稱:", size_hint=(.15, 1)) nameLabel.color = colorHex("#000000") nameLayout.add_widget(nameLabel) self.selfgroup_name_id = STextInput(text=self.selfgroup_name, size_hint=(.65, 1)) nameLayout.add_widget(self.selfgroup_name_id) nameLayout.add_widget(STableBoxLayout(size_hint=(.23, 1))) self.add_widget(nameLayout) self.add_widget(STableBoxLayout(size_hint=(1, None), height=1)) headLayout = STableGridLayout(cols=3, rows=1, spacing=2, size_hint=(1, None), height=30) headLabel = SHeadLabel(text="功能", size_hint=(.15, 1)) headLabel.halign: 'center' headLabel.valign: 'middle' headLayout.add_widget(headLabel) headLabel = SHeadLabel(text="代碼", size_hint=(.2, 1)) headLabel.halign: 'center' headLabel.valign: 'middle' headLayout.add_widget(headLabel) headLabel = SHeadLabel(text="名稱", size_hint=(.65, 1)) headLabel.halign: 'center' headLabel.valign: 'middle' headLayout.add_widget(headLabel) self.add_widget(headLayout) self.add_widget(STableBoxLayout(size_hint=(1, None), height=2)) self.def_ids = {} slview = STableScrollView() slview.size_hint = (1, None) slview.size = (360, 320) self.contentLayout = STableGridLayout(cols=3, spacing=2, size_hint_y=None) # Make sure the height is such that there is something to scroll. self.contentLayout.bind( minimum_height=self.contentLayout.setter('height')) tmpList = None stkName = None for stkId in self.selfStkList: tmpList = [] tmpList.append(stkId) stkName = self.app.stkNameDict.get(stkId) if stkName == None: tmpList.append("") else: tmpList.append(stkName) self.addListRow(tmpList) self.addInsertRow() slview.add_widget(self.contentLayout) self.add_widget(slview) bottomLayout = BoxLayout(size_hint=(1, None), height=30) self.ensurebtn_id = SButton(text="確定", size_hint=(.49, 1)) bottomLayout.add_widget(self.ensurebtn_id) bottomLayout.add_widget(BoxLayout(size_hint=(.02, 1))) self.cancelbtn_id = SButton(text="取消", size_hint=(.49, 1)) bottomLayout.add_widget(self.cancelbtn_id) self.add_widget(bottomLayout) def addListRow(self, alist): rowList = [] funcLayout = SBoxLayout(size_hint=(.15, None), height=30) funcLayout.orientation = "horizontal" funcLayout.padding = (1, 1, 1, 1) funcLayout.add_widget(BoxLayout(size_hint=(.1, 1))) btn = SInfoButton(extra_info=alist[0], text="刪", size_hint=(.8, 1)) btn.halign = "center" btn.valign = "middle" btn.bind(on_release=self.deleteRecordPopup) funcLayout.add_widget(btn) funcLayout.add_widget(BoxLayout(size_hint=(.1, 1))) rowList.append(funcLayout) self.contentLayout.add_widget(funcLayout) contentLabel = SContentLabel(text=alist[0][2:], size_hint=(.2, None), height=30) contentLabel.color = colorHex("#000000") contentLabel.halign = "center" contentLabel.valign = "middle" rowList.append(contentLabel) self.contentLayout.add_widget(contentLabel) contentLabel = SContentLabel(text=alist[1], size_hint=(.65, None), height=30) contentLabel.color = colorHex("#000000") contentLabel.halign = "left" contentLabel.valign = "middle" rowList.append(contentLabel) self.contentLayout.add_widget(contentLabel) self.def_ids[alist[0]] = rowList def deleteRow(self, rowId): rowList = self.def_ids.get(rowId) for obj in rowList: self.contentLayout.remove_widget(obj) self.def_ids.pop(rowId) if rowId in self.selfStkList: self.selfStkList.remove(rowId) def saveData(self): stkListStr = "" for stkId in self.selfStkList: stkListStr += stkId + "|" if len(stkListStr) != 0: stkListStr = stkListStr[0:-1] filePath = os.path.join( os.path.dirname(__file__), ".." + os.sep + "conf" + os.sep + "self_stkquote.ini") alist = sutil.getListFromFile(filePath) with open(filePath, 'w', encoding='utf-8') as f: for tmpStr in alist: aList = tmpStr.split(",") if int(aList[0]) == self.selfgroup_index: astr = str( self.selfgroup_index ) + "," + self.selfgroup_name_id.text + "," + stkListStr + "\n" else: astr = tmpStr + "\n" f.write(astr) def addInsertRow(self): rowList = [] funcLayout = SBoxLayout(size_hint=(.15, None), height=30) funcLayout.orientation = "horizontal" funcLayout.padding = (1, 1, 1, 1) funcLayout.add_widget(BoxLayout(size_hint=(.1, 1))) btn = SInfoButton(extra_info=INSERT_ROW_ID, text="新增", size_hint=(.8, 1)) btn.halign = "center" btn.valign = "middle" btn.bind(on_release=self.addRecordPopup) funcLayout.add_widget(btn) funcLayout.add_widget(BoxLayout(size_hint=(.1, 1))) rowList.append(funcLayout) self.contentLayout.add_widget(funcLayout) contentLabel = SContentLabel(text="", size_hint=(.2, None), height=30) contentLabel.halign = "center" contentLabel.valign = "middle" rowList.append(contentLabel) self.contentLayout.add_widget(contentLabel) contentLabel = SContentLabel(text="", size_hint=(.65, None), height=30) contentLabel.halign = "left" contentLabel.valign = "middle" rowList.append(contentLabel) self.contentLayout.add_widget(contentLabel) self.def_ids[INSERT_ROW_ID] = rowList def addRecordPopup(self, instance): refDict = {} for key in self.paramDict.keys(): refDict[key] = self.paramDict.get(key) self.add_scsLayout = StkQuery(refDict) self.add_popup = SPopup(title="新增自選股票", content=self.add_scsLayout, size_hint=(None, None), size=(480, 360), auto_dismiss=False) self.add_scsLayout.ensureBtn_id.bind(on_press=self.addRecordEvent) self.add_scsLayout.cancelBtn_id.bind(on_press=self.add_popup.dismiss) self.add_popup.title_font = CONSTS.FONT_NAME self.add_popup.open() def addRecordEvent(self, instance): self.add_scsLayout.doSelectStk() if len(self.add_scsLayout.selectIdNameList) == 0: return duplicatedIds = [] for aList in self.add_scsLayout.selectIdNameList: if aList[0] in self.selfStkList: duplicatedIds.append(aList[0][2:]) if len(duplicatedIds) != 0: self.app.showErrorView(True, CONSTS.ERR_STKID_DUPLICATED, duplicatedIds) return self.deleteRow(INSERT_ROW_ID) for aList in self.add_scsLayout.selectIdNameList: self.addListRow(aList) self.selfStkList.append(aList[0]) self.addInsertRow() self.add_popup.dismiss() def deleteRecordPopup(self, instance): self.deleteConfirm = SRowConfirmLayout() self.del_popup = SPopup(title="刪除自選股票", content=self.deleteConfirm, size_hint=(None, None), size=(240, 160), auto_dismiss=False) self.deleteConfirm.yesbtn_id.extra_info = instance.extra_info self.deleteConfirm.yesbtn_id.bind(on_press=self.deleteRecordEvent) self.deleteConfirm.nobtn_id.bind(on_press=self.del_popup.dismiss) self.del_popup.title_font = CONSTS.FONT_NAME self.del_popup.open() def deleteRecordEvent(self, instance): self.deleteRow(instance.extra_info) self.del_popup.dismiss()
class SStrategy(BoxLayout): def __init__(self, paramDict, **kwargs): super(SStrategy, self).__init__(**kwargs) self.paramDict = paramDict self.app = self.paramDict.get(CONSTS.S_APP) self.size_hint = (1, 1) self.orientation = "vertical" headLayout = STableGridLayout(cols=3, rows=1, spacing=2, size_hint=(1, None), height=30) headLabel = SHeadLabel(text="功能", size_hint=(.15, 1)) headLabel.halign: 'center' headLabel.valign: 'middle' headLayout.add_widget(headLabel) headLabel = SHeadLabel(text="策略名稱", size_hint=(.6, 1)) headLabel.halign: 'center' headLabel.valign: 'middle' headLayout.add_widget(headLabel) headLabel = SHeadLabel(text="檔案名稱", size_hint=(.25, 1)) headLabel.halign: 'center' headLabel.valign: 'middle' headLayout.add_widget(headLabel) self.add_widget(headLayout) gapLayout = STableBoxLayout(size_hint=(1, None), height=2) self.add_widget(gapLayout) self.maxIndex = 0 self.def_ids = {} slview = STableScrollView() slview.size_hint = (1, None) slview.size = (540, 350) self.contentLayout = STableGridLayout(cols=3, spacing=2, size_hint_y=None) # Make sure the height is such that there is something to scroll. self.contentLayout.bind(minimum_height=self.contentLayout.setter('height')) filePath = os.path.join(os.path.dirname(__file__), ".." + os.sep + "conf" + os.sep + "strategy.ini") if not os.path.exists(filePath): with open(filePath, 'w'): pass alist = sutil.getListFromFile(filePath) for astr in alist: tmpList = astr.strip().split(",") if len(tmpList) < 2: continue self.addListRow(tmpList, False) self.maxIndex += 1 self.addInsertRow(str(self.maxIndex)) slview.add_widget(self.contentLayout) self.add_widget(slview) closeLayout = BoxLayout(size_hint=(1, None), height=36) self.closebtn_id = SButton(text="關閉", size_hint=(1, 1)) closeLayout.add_widget(self.closebtn_id) self.add_widget(closeLayout) def addListRow(self, alist, aflag): if aflag: self.deleteRow(self.maxIndex) rowList = [] funcLayout = SBoxLayout(size_hint=(.25, None), height=30) funcLayout.orientation = "horizontal" funcLayout.padding = (1, 1, 1, 1) funcLayout.add_widget(BoxLayout(size_hint=(.06, 1))) btn = SInfoButton(extra_info=self.maxIndex, text="修", size_hint=(.14, 1)) btn.halign = "center" btn.valign = "middle" btn.bind(on_release=self.updateRecordPopup) funcLayout.add_widget(btn) funcLayout.add_widget(BoxLayout(size_hint=(.02, 1))) btn = SInfoButton(extra_info=self.maxIndex, text="刪", size_hint=(.14, 1)) btn.halign = "center" btn.valign = "middle" btn.bind(on_release=self.deleteRecordPopup) funcLayout.add_widget(btn) funcLayout.add_widget(BoxLayout(size_hint=(.02, 1))) btn = SInfoButton(extra_info=self.maxIndex, text="編輯策略", size_hint=(.56, 1)) btn.halign = "center" btn.valign = "middle" btn.bind(on_release=self.editContent) funcLayout.add_widget(btn) funcLayout.add_widget(BoxLayout(size_hint=(.06, 1))) rowList.append(funcLayout) self.contentLayout.add_widget(funcLayout) contentLabel = SContentLabel(text=alist[0], size_hint=(.5, None), height=30) contentLabel.color = colorHex("#000000") contentLabel.halign = "left" contentLabel.valign = "middle" rowList.append(contentLabel) self.contentLayout.add_widget(contentLabel) contentLabel = SContentLabel(text=alist[1], size_hint=(.25, None), height=30) contentLabel.color = colorHex("#000000") contentLabel.halign = "left" contentLabel.valign = "middle" rowList.append(contentLabel) self.contentLayout.add_widget(contentLabel) self.def_ids[self.maxIndex] = rowList def deleteRow(self, rowIndex): rowList = self.def_ids.get(rowIndex) for obj in rowList: self.contentLayout.remove_widget(obj) self.def_ids.pop(rowIndex) if rowList[2].text != "": filePath = os.path.abspath(os.path.join(save_dir, rowList[2].text)) if os.path.exists(filePath): os.remove(filePath) self.saveData() def saveData(self): keylist = self.def_ids.keys() keylist = sorted(keylist) listLen = len(keylist) filePath = os.path.join(os.path.dirname(__file__), ".." + os.sep + "conf" + os.sep + "strategy.ini") with open(filePath, 'w', encoding = 'utf-8') as f: rowList = None for i in range(0, listLen - 1): rowList = self.def_ids.get(keylist[i]) astr = rowList[1].text + "," + rowList[2].text + "\n" f.write(astr) def addInsertRow(self, strIndex): rowList = [] funcLayout = SBoxLayout(size_hint=(.25, None), height=30) funcLayout.orientation = "horizontal" funcLayout.padding = (1, 1, 1, 1) funcLayout.add_widget(BoxLayout(size_hint=(.1, 1))) btn = SButton(text="新增", size_hint=(.8, 1)) btn.halign = "center" btn.valign = "middle" btn.bind(on_release=self.addRecordPopup) funcLayout.add_widget(btn) funcLayout.add_widget(BoxLayout(size_hint=(.1, 1))) rowList.append(funcLayout) self.contentLayout.add_widget(funcLayout) contentLabel = SContentLabel(text="", size_hint=(.5, None), height=30) contentLabel.halign = "left" contentLabel.valign = "middle" rowList.append(contentLabel) self.contentLayout.add_widget(contentLabel) contentLabel = SContentLabel(text="", size_hint=(.25, None), height=30) contentLabel.halign = "left" contentLabel.valign = "middle" rowList.append(contentLabel) self.contentLayout.add_widget(contentLabel) self.def_ids[int(strIndex)] = rowList def addRecordPopup(self, instance): refDict = {} for key in self.paramDict.keys(): refDict[key] = self.paramDict.get(key) refDict['mode'] = "1" self.add_scsLayout = SStrategySetting(refDict) self.add_popup = SPopup(title="新增策略", content=self.add_scsLayout, size_hint=(None, None), size=(560, 440), auto_dismiss=False) self.add_scsLayout.ensurebtn_id.bind(on_press=self.addRecordEvent) self.add_scsLayout.closebtn_id.bind(on_press=self.add_popup.dismiss) self.add_popup.title_font = CONSTS.FONT_NAME self.add_popup.open() def addRecordEvent(self, instance): strategyName = self.add_scsLayout.strategy_id.text if strategyName == None or strategyName == "": self.app.showErrorView(True, CONSTS.ERR_STRATEGY_IS_SPACE) return dflag = False for akey in self.def_ids.keys(): rowList = self.def_ids.get(akey) if strategyName == rowList[1].text: dflag = True break if dflag: self.app.showErrorView(True, CONSTS.ERR_STRATEGY_DUPLICATED) return fileName = self.add_scsLayout.filename_id.text alist = [] alist.append(strategyName) alist.append(fileName) self.addListRow(alist, True) self.maxIndex += 1 self.addInsertRow(str(self.maxIndex)) self.saveData() self.add_popup.dismiss() self.filePathTmp = os.path.abspath(os.path.join(save_dir, fileName)) open(self.filePathTmp, 'a').close() threading.Thread(target=self.openFile).start() def openFile(self): os.system(self.filePathTmp) def updateRecordPopup(self, instance): refDict = {} for key in self.paramDict.keys(): refDict[key] = self.paramDict.get(key) refDict['mode'] = "2" self.update_scsLayout = SStrategySetting(refDict) self.update_popup = SPopup(title="修改策略", content=self.update_scsLayout, size_hint=(None, None), size=(560, 440), auto_dismiss=False) self.update_scsLayout.ensurebtn_id.extra_info = instance.extra_info self.update_scsLayout.ensurebtn_id.bind(on_press=self.updateRecordEvent) self.update_scsLayout.closebtn_id.bind(on_press=self.update_popup.dismiss) self.update_popup.title_font = CONSTS.FONT_NAME rowList = self.def_ids.get(instance.extra_info) self.update_scsLayout.strategy_id.text = rowList[1].text self.update_scsLayout.filename_id.text = rowList[2].text self.update_popup.open() def updateRecordEvent(self, instance): rowIndex = instance.extra_info strategyName = self.update_scsLayout.strategy_id.text if strategyName == None or strategyName == "": self.app.showErrorView(True, CONSTS.ERR_STRATEGY_IS_SPACE) return fileName = self.update_scsLayout.filename_id.text dflag = False for akey in self.def_ids.keys(): if akey == rowIndex: continue rowList = self.def_ids.get(akey) if strategyName == rowList[1].text and fileName == rowList[2].text: dflag = True break if dflag: self.app.showErrorView(True, CONSTS.ERR_STRATEGY_DUPLICATED) return rowList = self.def_ids.get(rowIndex) rowList[1].text = strategyName self.saveData() self.update_popup.dismiss() self.filePathTmp = os.path.abspath(os.path.join(save_dir, fileName)) threading.Thread(target=self.openFile).start() def deleteRecordPopup(self, instance): self.deleteConfirm = SRowConfirmLayout() self.del_popup = SPopup(title="刪除策略", content=self.deleteConfirm, size_hint=(None, None), size=(240, 160), auto_dismiss=False) self.deleteConfirm.yesbtn_id.extra_info = instance.extra_info self.deleteConfirm.yesbtn_id.bind(on_press=self.deleteRecordEvent) self.deleteConfirm.nobtn_id.bind(on_press=self.del_popup.dismiss) self.del_popup.title_font = CONSTS.FONT_NAME self.del_popup.open() def deleteRecordEvent(self, instance): self.deleteRow(instance.extra_info) self.del_popup.dismiss() def editContent(self, instance): rowList = self.def_ids.get(int(instance.extra_info)) filePath = os.path.join(save_dir, rowList[2].text) os.system(os.path.abspath(filePath))
class StkQuote(BoxLayout): head_layout = ObjectProperty(None) body_layout = ObjectProperty(None) selfStkList = ObjectProperty(None) subscribeList = ObjectProperty(None) def __init__(self, paramDict, **kwargs): super(StkQuote, self).__init__(**kwargs) self.lock = threading.RLock() self.size_hint = (1, 1) self.orientation = "vertical" self.paramDict = paramDict self.app = self.paramDict.get(CONSTS.S_APP) self.dispIdName = self.paramDict.get("dispIdName", True) self.headDict = self.paramDict.get("headDict") self.headIdList = [] self.headIdList.append("id") self.headIdList.append("name") for aKey in self.headDict.keys(): if aKey == "id" or aKey == "name": continue else: self.headIdList.append(aKey) self.fieldIdList = [] #記錄資料的欄位列表(不包含id及name欄位) self.dispIdList = [] #記錄顯示的欄位列表 """ if self.dispIdName == True: self.dispIdList內容為 ['id','name','price','vol', ...] else: self.dispIdList內容為 ['id'(or 'name'),'price','vol', ...] """ self.fieldMapping = {} #記錄資料欄位與顯示欄位的對應,''代表畫面不顯示此欄位 """ if self.dispIdName == True: {'id':'0', 'name':'1', 'price':'2', 'vol':'3', ...,} else: {'name':'0'(or 'id':'0'), 'price':'1', 'vol':'2', ...,} """ self.dispFieldMapping = {} #記錄顯示欄位與資料欄位的對應 """ if self.dispIdName == True: {'0':'id', '1':'name', '2':'price', '3':'vol', ...} else: {'0':'name'(or '0':'id'), '1':'price', '2':'vol', ...} """ # 1001-Begin: 以下將欄位訊息儲存至相關的變數中 shiftIdx = 1 self.fieldMapping["name"] = "0" if self.dispIdName == True: self.fieldMapping["id"] = "0" self.dispFieldMapping["0"] = "id" self.dispIdList.append("id") self.fieldMapping["name"] = "1" self.dispFieldMapping["1"] = "name" self.dispIdList.append("name") shiftIdx = 0 else: self.dispIdList.append("name") self.fieldMapping["id"] = "" self.dispFieldMapping["0"] = "name" for idx in range(2, len(self.headIdList)): self.fieldIdList.append(self.headIdList[idx]) if (idx - shiftIdx) >= COLUMN_NUM: self.fieldMapping[self.headIdList[idx]] = "" else: self.fieldMapping[self.headIdList[idx]] = str(idx - shiftIdx) self.dispFieldMapping[str(idx - shiftIdx)] = self.headIdList[idx] self.dispIdList.append(self.headIdList[idx]) self.headButtonList = [] #記錄標題之Button List self.quoteBaseDict = {} #記錄股票基本資料之字典 self.quoteDataDict = {} #記錄所有報價資料之字典 """self.quoteDataDict資料格式如下所示: stkid: {'id': [stkId,fg_color,bg_color],'name': [stkName,fg_color,bg_color],'price': [priceValue,fg_color,bg_color], ...} example: 'T11101': {'id':['T11101','#000000','#FFFFFF'],'name':['台泥','#000000','#FFFFFF'],'price':[10.0,'#000000','#FFFFFF']} """ self.dispDict = {} #記錄顯示物件的字典 """self.dispDict資料格式如下所示: {stkid:{'0':Kivy Object, '1': Kivy Object, ....},stkid:{'0':Kivy Object, '1': Kivy Object, ....}} """ headNum = len(self.dispFieldMapping) #取得畫面顯示的欄位數 self.headLayout = STableGridLayout(cols=headNum, rows=1, spacing=2, size_hint=(1, 1)) #1000-Start: 計算欄位寬度的size_hint if headNum < COLUMN_NUM: #如果欄位數比預設欄位數少 self.idWidth_hint = 1.0 / headNum self.otherWidth_hint = self.idWidth_hint else: self.idWidth_hint = 0.1 addWidth_hint = 0.1 addField = 1 if self.dispIdName == True: addWidth_hint += 0.1 addField += 1 self.otherWidth_hint = (1.0 - addWidth_hint) / (headNum - addField) #1000-End. for colIndexStr in self.dispFieldMapping.keys(): headId = self.dispFieldMapping.get(colIndexStr) field = self.headDict.get(headId) if headId == "id" or headId == "name": headButton = SHeadSortedButton(headText = field, headIndex = headId, text = field, size_hint = (self.idWidth_hint, 1)) else: headButton = SHeadSortedButton(headText = field, headIndex = headId, text = field, size_hint = (self.otherWidth_hint, 1)) self.headLayout.add_widget(headButton) self.headButtonList.append(headButton) self.head_layout.add_widget(self.headLayout) self.contentLayout = STableGridLayout(cols=headNum, spacing=2, size_hint_y=None) # Make sure the height is such that there is something to scroll. self.contentLayout.bind(minimum_height=self.contentLayout.setter('height')) self.body_layout.add_widget(self.contentLayout) def setStkList(self, selfStkList): self.selfStkList = selfStkList def setSubscribeList(self, subscribeList): self.subscribeList = subscribeList def setGroupName(self, groupName): self.groupName = groupName def _getDefaultDict(self): aDict = {} for headId in self.headIdList: aDict[headId] = ['', DEFAULT_FGCOLOR, DEFAULT_BGCOLOR] return aDict @synchronized_with_attr("lock") def _getDefaultRowDict(self, aDict): dispObjDict = {} for colIndexStr in self.dispFieldMapping.keys(): headId = self.dispFieldMapping.get(colIndexStr) fieldList = aDict.get(headId) contentObj = None if headId == "id": contentObj = SButton(size_hint = (self.idWidth_hint, None), height=30) contentObj.text = fieldList[0] contentObj.halign = "center" contentObj.bind(on_press=self._id_press) elif headId == "name": contentObj = SButton(size_hint = (self.idWidth_hint, None), height=30) contentObj.text = fieldList[0] contentObj.halign = "center" contentObj.bind(on_press=self._name_press) else: contentObj = SContentLabel(size_hint = (self.otherWidth_hint, None), height=30) contentObj.text = fieldList[0] contentObj.color = colorHex(fieldList[1]) if headId == "TT": contentObj.halign = "center" else: contentObj.halign = "right" dispObjDict[colIndexStr] = contentObj return dispObjDict def _openOptionPopup(self): content = BoxLayout(size_hint=(1, 1), orientation="vertical") strendBtn = SButton(text="走勢圖", size_hint=(1, None), height=30) strendBtn.bind(on_press=self._openStrendChart) content.add_widget(strendBtn) content.add_widget(BoxLayout(size_hint=(1, None), height=1)) stechBtn = SButton(text="技術分析", size_hint=(1, None), height=30) stechBtn.bind(on_press=self._openStechChart) content.add_widget(stechBtn) content.add_widget(BoxLayout(size_hint=(1, None), height=1)) closeBtn = SButton(text="關閉", size_hint=(1, None), height=30) content.add_widget(closeBtn) titleName = self.oneStkDict.get("id") + " " + self.oneStkDict.get("name") self.option_popup = SPopup(title=titleName, content=content, title_font=CONSTS.FONT_NAME, size_hint=(None, None), size=(240, 152), auto_dismiss=False) closeBtn.bind(on_press=self.option_popup.dismiss) self.option_popup.open() def _id_press(self, instance): self.oneStkDict = {} currIdx = -1 for aKey in self.quoteBaseDict.keys(): currIdx += 1 if instance.text == aKey[2:]: self.oneStkDict = self.quoteBaseDict.get(aKey) break self.currIndex = currIdx self._openOptionPopup() def _name_press(self, instance): self.oneStkDict = {} currIdx = -1 for aKey in self.quoteBaseDict.keys(): currIdx += 1 aDict = self.quoteBaseDict.get(aKey) if instance.text == aDict.get("name"): self.oneStkDict = aDict break self.currIndex = currIdx self._openOptionPopup() def _openStrendChart(self, instance): self.option_popup.dismiss() refParam = {} refParam[CONSTS.S_APP] = self.app refParam["ChartType"] = "1" refParam["GroupName"] = self.groupName refParam["SelfStkList"] = self.selfStkList refParam["SubscribeList"] = self.subscribeList refParam["QuoteBaseDict"] = self.quoteBaseDict refParam["OneStkDict"] = self.oneStkDict self.stcLayout = StkGroupView(refParam) self.strend_popup = SPopup(title="走勢圖&技術分析", content=self.stcLayout, size_hint=(None, None), size=(720, 540), auto_dismiss=False) self.stcLayout.closebtn_id.bind(on_press=self._strend_popup_dismiss) self.strend_popup.title_font = CONSTS.FONT_NAME self.strend_popup.open() def _strend_popup_dismiss(self, instance): self.strend_popup.dismiss() self.stcLayout.removeListener() def _openStechChart(self, instance): self.option_popup.dismiss() refParam = {} refParam[CONSTS.S_APP] = self.app refParam["ChartType"] = "2" refParam["GroupName"] = self.groupName refParam["SelfStkList"] = self.selfStkList refParam["SubscribeList"] = self.subscribeList refParam["QuoteBaseDict"] = self.quoteBaseDict refParam["OneStkDict"] = self.oneStkDict self.sttLayout = StkGroupView(refParam) self.stech_popup = SPopup(title="走勢圖&技術分析", content=self.sttLayout, size_hint=(None, None), size=(720, 540), auto_dismiss=False) self.sttLayout.closebtn_id.bind(on_press=self._stech_popup_dismiss) self.stech_popup.title_font = CONSTS.FONT_NAME self.stech_popup.open() def _stech_popup_dismiss(self, instance): self.stech_popup.dismiss() self.sttLayout.removeListener() @synchronized_with_attr("lock") def updateBaseQuote(self, baseList): for aDict in baseList: stkId = aDict.get("id") if stkId == None: continue else: existDict = self.quoteBaseDict.get(stkId) if existDict == None: #若無報價基本資料,創建一新的字典 existDict = {} tmpId = None for headId in aDict.keys(): existDict[headId] = aDict.get(headId) self.quoteBaseDict[stkId] = existDict @synchronized_with_attr("lock") def updateQuote(self, quoteList): """ """ if quoteList == None or len(quoteList) == 0: return #5001-Start: 若無id欄位,則不添加至報價列表;若資料已存在,則更新資料 for aDict in quoteList: id_dataList = aDict.get("id") if id_dataList == None: continue else: existFlag = True stkId = id_dataList[0] existDict = self.quoteDataDict.get(stkId) if existDict == None: #若無報價資料,初始化一筆報價資料 existFlag = False existDict = self._getDefaultDict() # 初始化報價資料 dispObjDict = None if existFlag == True: #若已存在報價資料,則直接取得畫面上顯示之物件 dispObjDict = self.dispDict.get(stkId) else: #若無報價資料,則初始化一筆畫面上顯示之物件 dispObjDict = self._getDefaultRowDict(existDict) self.dispDict[stkId] = dispObjDict for rowNum in dispObjDict.keys(): self.contentLayout.add_widget(dispObjDict.get(rowNum)) tmpId = None for headId in aDict.keys(): tmpHeadId = existDict.get(headId) if tmpHeadId != None: existDict[headId] = aDict.get(headId) fieldIdx = self.fieldMapping.get(headId) #取得欄位對應之顯示欄位的index if fieldIdx != None and fieldIdx != "": kvObj = dispObjDict.get(fieldIdx) valueList = aDict.get(headId) if headId == "id": kvObj.text = valueList[0][2:] else: kvObj.text = valueList[0] if headId != "id" and headId != "name": kvObj.color = colorHex(valueList[1]) time.sleep(0.0001) # 2020/10/28 調整,因應欄位顯示空白問題 self.quoteDataDict[stkId] = existDict #5001-End. @synchronized_with_attr("lock") def clearQuote(self): if self.contentLayout != None: self.contentLayout.clear_widgets() self.quoteBaseDict.clear() self.quoteDataDict.clear() self.dispDict.clear() @synchronized_with_attr("lock") def resetFieldsSeq(self, fieldIdList): self.fieldIdList = fieldIdList headIdIndex = -1 for aObj in self.headButtonList: if aObj.headIndex == "id" or aObj.headIndex == "name": continue headIdIndex += 1 headId = self.fieldIdList[headIdIndex] aObj.headIndex = headId aObj.text = self.headDict.get(headId) self._shiftDispField() @synchronized_with_attr("lock") def nextField(self): removeId = self.fieldIdList.pop(0) self.fieldIdList.append(removeId) headIdIndex = -1 for aObj in self.headButtonList: if aObj.headIndex == "id" or aObj.headIndex == "name": continue headIdIndex += 1 headId = self.fieldIdList[headIdIndex] aObj.headIndex = headId aObj.text = self.headDict.get(headId) self._shiftDispField() @synchronized_with_attr("lock") def previousField(self): removeId = self.fieldIdList.pop(-1) self.fieldIdList.insert(0, removeId) headIdIndex = -1 for aObj in self.headButtonList: if aObj.headIndex == "id" or aObj.headIndex == "name": continue headIdIndex += 1 headId = self.fieldIdList[headIdIndex] aObj.headIndex = headId aObj.text = self.headDict.get(headId) self._shiftDispField() def _shiftDispField(self): for headId in self.fieldMapping.keys(): #將id及name以外的欄位,重新設置欄位對應 if headId == "id" or headId == "name": continue self.fieldMapping[headId] = "" headIdIndex = -1 for colIndexStr in self.dispFieldMapping.keys(): headId = self.dispFieldMapping.get(colIndexStr) if headId == "id" or headId == "name": continue headIdIndex += 1 headId = self.fieldIdList[headIdIndex] self.dispFieldMapping[colIndexStr] = headId self.fieldMapping[headId] = colIndexStr for stkId in self.dispDict.keys(): dispObjDict = self.dispDict.get(stkId) aQuoteDict = self.quoteDataDict.get(stkId) for rowNum in dispObjDict.keys(): kvObj = dispObjDict.get(rowNum) headId = self.dispFieldMapping.get(rowNum) aDataList = aQuoteDict.get(headId) if headId == "id": kvObj.text = aDataList[0][2:] else: kvObj.text = aDataList[0] kvObj.color = colorHex(aDataList[1]) if headId == "id" or headId == "name" or headId == "TT": kvObj.halign = "center" else: kvObj.halign = "right"
class SelfStkQuote(BoxLayout): body_layout = ObjectProperty(None) content_layout = ObjectProperty(None) selfgroup_id = ObjectProperty(None) page_id = ObjectProperty(None) totalpage_id = ObjectProperty(None) prepage_id = ObjectProperty(None) nextpage_id = ObjectProperty(None) fieldRight_id = ObjectProperty(None) fieldLeft_id = ObjectProperty(None) selfgroup_index = 0 selfStkList = [] def __init__(self, paramDict, **kwargs): super(SelfStkQuote, self).__init__(**kwargs) self.paramDict = paramDict self.app = self.paramDict.get(CONSTS.S_APP) self.quoteDataDict = {} self.selfDict = {} self.selfDropDown = SSelfDropDown() self.dropDownDict = {} firstRecord = True selfGroupList = None filePath = os.path.join( os.path.dirname(__file__), ".." + os.sep + "conf" + os.sep + "self_stkquote.ini") alist = sutil.getListFromFile(filePath) for astr in alist: selfGroupList = astr.strip().split(",") if len(selfGroupList) < 3: continue if firstRecord: firstRecord = False self.selfgroup_id.text = selfGroupList[1] self.selfgroup_index = int(selfGroupList[0]) self.selfDict[int(selfGroupList[0])] = selfGroupList abtn = SInfoButton(extra_info=int(selfGroupList[0]), text=selfGroupList[1]) abtn.size_hint_y = None abtn.height = 30 abtn.bind(on_release=self.selfDropDown.select) self.selfDropDown.add_widget(abtn) self.dropDownDict[str(abtn.extra_info)] = abtn self.selfgroup_id.bind(on_release=self.selfDropDown.open) self.selfDropDown.bind(on_select=self.selfSelect) self.stkidList = [] self.num_per_page = NUM_PER_PAGE self.page_num = 1 self.max_page_num = 1 self.page_id.bind(on_text_validate=self._on_page_id_enter) filePath = os.path.join( os.path.dirname(__file__), ".." + os.sep + "conf" + os.sep + "stkfields_setting.ini") alist = sutil.getListFromFile(filePath) headDefineDict = {} for astr in alist: astrList = astr.strip().split(",") if len(astrList) < 2: continue headDefineDict[astrList[0]] = astrList[1] headDict = {} headDict["id"] = headDefineDict.get("id") #SID headDict["name"] = headDefineDict.get("name") #SNT seqStr = headDefineDict.get("_SEQ_") seqStrList = seqStr.split("|") for headId in seqStrList: headDict[headId] = headDefineDict.get(headId) self.stkquote = StkQuote({ CONSTS.S_APP: self.app, 'headDict': headDict, 'dispIdName': True }) self.body_layout.remove_widget(self.content_layout) self.content_layout = self.stkquote self.content_layout.size_hint = (1, 1) self.body_layout.add_widget(self.content_layout) Clock.schedule_once(self.doQuoteStart, .5) #此段用意為讓畫面先顯示出來,再做後續的動作 def selfSelect(self, instance, atext): self.selfgroup_id.text = atext.text self.selfgroup_index = atext.extra_info self.stkquote.clearQuote() #變更自選組合,先清掉之前的畫面 selfStkListStr = self.selfDict.get(self.selfgroup_index)[2] #取得新的自選組合 if selfStkListStr == "" or len(selfStkListStr) == 0: self.selfStkList = [] else: self.selfStkList = selfStkListStr.split("|") self._calcPageInfo() self.subscribeQuote() #重新訂閱股票 def _stkSetting(self): if len(self.app.stkNameDict) == 0: self._doQueryStktbl() else: refParam = {} refParam[CONSTS.S_APP] = self.app refParam["SelfGroupIndex"] = self.selfgroup_index refParam["SelfGroupName"] = self.selfgroup_id.text refParam["SelfStkList"] = list(self.selfStkList) stcLayout = SelfStkSetting(refParam) self.stcLayout = stcLayout self.self_setting_popup = SPopup(title="自選設定", content=stcLayout, size_hint=(None, None), size=(360, 480), auto_dismiss=False) stcLayout.ensurebtn_id.bind(on_press=self._changeGroup) stcLayout.cancelbtn_id.bind( on_press=self._self_setting_popup_dismiss) self.self_setting_popup.title_font = CONSTS.FONT_NAME self.self_setting_popup.open() def _fieldsSetting(self): refParam = {} refParam[CONSTS.S_APP] = self.app sfsLayout = SFieldSetting(refParam) self.sfsLayout = sfsLayout self.self_fieldsetting_popup = SPopup(title="欄位排序", content=sfsLayout, size_hint=(None, None), size=(300, 480), auto_dismiss=False) sfsLayout.ensurebtn_id.bind(on_press=self._changeFields) sfsLayout.closebtn_id.bind( on_press=self.self_fieldsetting_popup.dismiss) self.self_fieldsetting_popup.title_font = CONSTS.FONT_NAME self.self_fieldsetting_popup.open() def _doQueryStktbl(self): gwParam = {} gwParam['PinyinType'] = "1" gwParam['LanguageID'] = "T" gwParam['ExchangeID'] = "TW" sysConfDict = self.app.confDict.get(CONSTS.SYS_CONF_DICT) refParam = {} refParam["CONSTS.S_APP"] = self.app refParam["TitleMsg"] = sysConfDict.get("MSG_TITLE") refParam["InfoMsg"] = " 股名檔下載中..." refParam["PopupSize"] = (160, 120) refParam["GwParam"] = gwParam refParam["GwFunc"] = abxtoolkit.query_stktbl1 refParam["ResultFunc"] = self._finishedQueryStktbl sgwPopup = SGwPopup(refParam) sgwPopup.processEvent() def _finishedQueryStktbl(self, gwResult): filePath = os.path.join( os.path.dirname(__file__), ".." + os.sep + "rowdata" + os.sep + "stktbl1TTW.dat") alist = sutil.getListFromFile(filePath) alist.pop(0) tmpList = None for astr in alist: if astr == "" or len(astr) == 0: continue tmpList = astr.strip().split("|") if len(tmpList) < 2: continue self.app.stkNameDict[tmpList[0]] = tmpList[1] refParam = {} refParam[CONSTS.S_APP] = self.app refParam["SelfGroupIndex"] = self.selfgroup_index refParam["SelfGroupName"] = self.selfgroup_id.text refParam["SelfStkList"] = list(self.selfStkList) stcLayout = SelfStkSetting(refParam) self.stcLayout = stcLayout self.self_setting_popup = SPopup(title="自選設定", content=stcLayout, size_hint=(None, None), size=(360, 480), auto_dismiss=False) stcLayout.ensurebtn_id.bind(on_press=self._changeGroup) stcLayout.cancelbtn_id.bind(on_press=self._self_setting_popup_dismiss) self.self_setting_popup.title_font = CONSTS.FONT_NAME self.self_setting_popup.open() def _self_setting_popup_dismiss(self, instance): self.self_setting_popup.dismiss() self.self_setting_popup.clear_widgets() def _changeGroup(self, instance): self.stcLayout.saveData() self._self_setting_popup_dismiss(instance) selfgroup_index = self.stcLayout.selfgroup_index selfgroup_name = self.stcLayout.selfgroup_name_id.text self.selfgroup_id.text = selfgroup_name adropdownBtn = self.dropDownDict[str(selfgroup_index)] adropdownBtn.text = selfgroup_name self.selfStkList = list(self.stcLayout.selfStkList) self.selfDict[selfgroup_index][1] = selfgroup_name stkListStr = "" for stkId in self.selfStkList: stkListStr += stkId + "|" if len(stkListStr) != 0: stkListStr = stkListStr[0:-1] self.selfDict[selfgroup_index][2] = stkListStr self.stkquote.clearQuote() #變更自選組合,先清掉之前的畫面 self._calcPageInfo() self.subscribeQuote() #重新訂閱股票 def _changeFields(self, instance): self.sfsLayout.saveData() self.self_fieldsetting_popup.dismiss(instance) self.stkquote.resetFieldsSeq(self.sfsLayout.fieldSeqList) #變更欄位順序 def doQuoteStart(self, instance): threading.Thread(target=self.doQuote).start() def _on_page_id_enter(self, instance): topage_num = int(instance.text) pageNum = 0 if topage_num < 1: pageNum = 1 elif topage_num > self.max_page_num: pageNum = self.max_page_num else: pageNum = topage_num self.page_id.text = str(pageNum) if pageNum == self.page_num: return self.page_num = pageNum self.stkquote.clearQuote() #變更自選組合,先清掉之前的畫面 self.subscribeQuote() #重新訂閱股票 def _onChangePage(self, changePage): if changePage == "NextPage": if self.page_num == self.max_page_num: self.page_num = 1 else: self.page_num += 1 elif changePage == "PrePage": if self.page_num == 1: self.page_num = self.max_page_num else: self.page_num -= 1 else: topage_num = int(changePage) if topage_num < 1: self.page_num = 1 elif topage_num > self.max_page_num: self.page_num = self.max_page_num self.topage_txt = str(self.page_num) self.page_id.text = str(self.page_num) self.prepage_id.disabled = True self.nextpage_id.disabled = True self.stkquote.clearQuote() #變更自選組合,先清掉之前的畫面 self.subscribeQuote() #重新訂閱股票 self.prepage_id.disabled = False self.nextpage_id.disabled = False def _calcPageInfo(self): stkListNum = len(self.selfStkList) if stkListNum == 0: self.prepage_id.disabled = True self.nextpage_id.disabled = True self.fieldRight_id.disabled = True self.fieldLeft_id.disabled = True self.page_id.text = "1" self.page_id.disabled = True self.totalpage_id.text = "1" return self.max_page_num = int(stkListNum / self.num_per_page) tmpNum = stkListNum % self.num_per_page if tmpNum != 0: self.max_page_num += 1 if self.max_page_num == 1: self.prepage_id.disabled = True self.nextpage_id.disabled = True else: self.prepage_id.disabled = False self.nextpage_id.disabled = False if self.page_num > self.max_page_num: self.page_num = self.max_page_num self.page_id.text = str(self.page_num) self.totalpage_id.text = str(self.max_page_num) if self.max_page_num == 1: self.page_id.disabled = True else: self.page_id.disabled = False self.fieldRight_id.disabled = False self.fieldLeft_id.disabled = False def _onFieldShift(self, changePage): if changePage == "fieldRight": self.fieldRight_id.disabled = True self.stkquote.nextField() self.fieldRight_id.disabled = False elif changePage == "fieldLeft": self.fieldLeft_id.disabled = True self.stkquote.previousField() self.fieldLeft_id.disabled = False def my_callback_func(self, a_result): if a_result.errcode != 0: self.app.showErrorView(False, a_result.errcode, a_result.errdes) return if a_result.stkid == None: return if a_result.stkid not in self.selfStkList: return if a_result.mesgtype == abxtoolkit.WATCH_TYPE.stkBase: aQuoteDict = self.quoteDataDict.get(a_result.stkid) if aQuoteDict == None: aQuoteDict = {} self.quoteDataDict[a_result.stkid] = aQuoteDict quoteList = [] aDict = {} baseList = [] baseDict = {} aDict["id"] = [a_result.stkid, DEFAULT_FGCOLOR, DEFAULT_BGCOLOR] baseDict["id"] = a_result.stkid if "SID" in a_result.data: aDict["id"] = [ a_result.data["SID"], DEFAULT_FGCOLOR, DEFAULT_BGCOLOR ] aQuoteDict["id"] = a_result.data["SID"] if "SNT" in a_result.data: aDict["name"] = [ a_result.data["SNT"], DEFAULT_FGCOLOR, DEFAULT_BGCOLOR ] aQuoteDict["name"] = a_result.data["SNT"] baseDict["name"] = a_result.data["SNT"] if "OT" in a_result.data: baseDict["OT"] = a_result.data["OT"] if "CloseT" in a_result.data: baseDict["CloseT"] = a_result.data["CloseT"] if "Dec" in a_result.data: baseDict["Dec"] = a_result.data["Dec"] quoteList.append(aDict) self.stkquote.updateQuote(quoteList) baseList.append(baseDict) self.stkquote.updateBaseQuote(baseList) if a_result.mesgtype == abxtoolkit.WATCH_TYPE.stkInfo: aQuoteDict = self.quoteDataDict.get(a_result.stkid) if aQuoteDict == None: aQuoteDict = {} self.quoteDataDict[a_result.stkid] = aQuoteDict quoteList = [] aDict = {} baseList = [] baseDict = {} aDict["id"] = [a_result.stkid, DEFAULT_FGCOLOR, DEFAULT_BGCOLOR] baseDict["id"] = a_result.stkid if "YP" in a_result.data: aDict["YP"] = [ "{:.2f}".format(a_result.data["YP"]), DEFAULT_FGCOLOR, DEFAULT_BGCOLOR ] aQuoteDict["YP"] = a_result.data["YP"] self._calcUpDown(a_result.stkid, aDict) baseDict["YP"] = a_result.data["YP"] if "USP" in a_result.data: aDict["USP"] = [ "{:.2f}".format(a_result.data["USP"]), DEFAULT_FGCOLOR, DEFAULT_BGCOLOR ] if "DSP" in a_result.data: aDict["DSP"] = [ "{:.2f}".format(a_result.data["DSP"]), DEFAULT_FGCOLOR, DEFAULT_BGCOLOR ] if "LTD" in a_result.data: baseDict["LTD"] = a_result.data["LTD"] quoteList.append(aDict) self.stkquote.updateQuote(quoteList) baseList.append(baseDict) self.stkquote.updateBaseQuote(baseList) if a_result.mesgtype == abxtoolkit.WATCH_TYPE.trade: aQuoteDict = self.quoteDataDict.get(a_result.stkid) if aQuoteDict == None: aQuoteDict = {} self.quoteDataDict[a_result.stkid] = aQuoteDict quoteList = [] aDict = {} aDict["id"] = [a_result.stkid, DEFAULT_FGCOLOR, DEFAULT_BGCOLOR] if "TT" in a_result.data: aDict["TT"] = [ sutil.formatTime(a_result.data["TT"]), DEFAULT_FGCOLOR, DEFAULT_BGCOLOR ] if "TP" in a_result.data: aDict["TP"] = [ "{:.2f}".format(a_result.data["TP"]), DEFAULT_FGCOLOR, DEFAULT_BGCOLOR ] aQuoteDict["TP"] = a_result.data["TP"] self._calcUpDown(a_result.stkid, aDict) if "TV" in a_result.data: aDict["TV"] = [ str(a_result.data["TV"]), DEFAULT_FGCOLOR, DEFAULT_BGCOLOR ] quoteList.append(aDict) self.stkquote.updateQuote(quoteList) if a_result.mesgtype == abxtoolkit.WATCH_TYPE.others: quoteList = [] aDict = {} aDict["id"] = [a_result.stkid, DEFAULT_FGCOLOR, DEFAULT_BGCOLOR] if "OP" in a_result.data: aDict["OP"] = [ "{:.2f}".format(a_result.data["OP"]), DEFAULT_FGCOLOR, DEFAULT_BGCOLOR ] if "HP" in a_result.data: aDict["HP"] = [ "{:.2f}".format(a_result.data["HP"]), DEFAULT_FGCOLOR, DEFAULT_BGCOLOR ] if "LP" in a_result.data: aDict["LP"] = [ "{:.2f}".format(a_result.data["LP"]), DEFAULT_FGCOLOR, DEFAULT_BGCOLOR ] quoteList.append(aDict) self.stkquote.updateQuote(quoteList) if a_result.mesgtype == abxtoolkit.WATCH_TYPE.order_1: quoteList = [] aDict = {} aDict["id"] = [a_result.stkid, DEFAULT_FGCOLOR, DEFAULT_BGCOLOR] if "BP" in a_result.data: aDict["BP"] = [ "{:.2f}".format(a_result.data["BP"]), DEFAULT_FGCOLOR, DEFAULT_BGCOLOR ] if "BV" in a_result.data: aDict["BV"] = [ str(a_result.data["BV"]), DEFAULT_FGCOLOR, DEFAULT_BGCOLOR ] if "AP" in a_result.data: aDict["AP"] = [ "{:.2f}".format(a_result.data["AP"]), DEFAULT_FGCOLOR, DEFAULT_BGCOLOR ] if "AV" in a_result.data: aDict["AV"] = [ str(a_result.data["AV"]), DEFAULT_FGCOLOR, DEFAULT_BGCOLOR ] quoteList.append(aDict) self.stkquote.updateQuote(quoteList) def _calcUpDown(self, stkid, aDict): aQuoteDict = self.quoteDataDict.get(stkid) yp = aQuoteDict.get("YP") #昨收價 if yp == None: return tp = aQuoteDict.get("TP") #成交價 if tp == None: return upDown = tp - yp fgColor = None if upDown < 0: fgColor = DEFAULT_DOWNCOLOR elif upDown > 0: fgColor = DEFAULT_UPCOLOR else: fgColor = DEFAULT_FGCOLOR aDict["UD"] = ["{:.2f}".format(upDown), fgColor, DEFAULT_BGCOLOR] aDict["TP"] = ["{:.2f}".format(tp), fgColor, DEFAULT_BGCOLOR] def closeStkQuote(self): abxtoolkit.remove_all_listener() def doQuote(self): r = abxtoolkit.add_listener([self.my_callback_func]) if self.selfgroup_index not in self.selfDict: return selfStkListStr = self.selfDict.get(self.selfgroup_index)[2] if selfStkListStr == "" or len(selfStkListStr) == 0: self._calcPageInfo() return self.selfStkList = selfStkListStr.split("|") self._calcPageInfo() self.subscribeQuote() def subscribeQuote(self): if len(self.selfStkList) == 0: quote_condition = [] else: startIdx = (self.page_num - 1) * NUM_PER_PAGE endIdx = self.page_num * NUM_PER_PAGE if endIdx > len(self.selfStkList): endIdx = len(self.selfStkList) subscribeList = [] quote_condition = [] for idx in range(startIdx, endIdx): stkId = self.selfStkList[idx] if stkId == "" or len(stkId) == 0: continue a_sub_stock = abxtoolkit.abx_quote_condition() a_sub_stock.stockID = stkId a_sub_stock.quoteID = [ 'stkBase', 'stkInfo', 'order_1', 'trade', 'others' ] quote_condition.append(a_sub_stock) subscribeList.append(stkId) self.stkquote.setStkList(self.selfStkList) self.stkquote.setSubscribeList(subscribeList) self.stkquote.setGroupName(self.selfgroup_id.text) r = abxtoolkit.subscribe_quote(quote_condition)
class SExecTrade(BoxLayout): rowdata_id = ObjectProperty(None) strategy_id = ObjectProperty(None) savefile_id = ObjectProperty(None) ensurebtn_id = ObjectProperty(None) closebtn_id = ObjectProperty(None) def __init__(self, paramDict, **kwargs): super(SExecTrade, self).__init__(**kwargs) self.paramDict = paramDict self.app = self.paramDict.get(CONSTS.S_APP) self.sysConfDict = self.app.confDict.get(CONSTS.SYS_CONF_DICT) self.strategyDict = {} self.rowdata_id.bind(focus=self.onRowdataFocus) self.strategyDropDown = SStrategyDropDown() firstRecord = True strategyList = None filePath = os.path.join(os.path.dirname(__file__), ".." + os.sep + "conf" + os.sep + "strategy.ini") alist = sutil.getListFromFile(filePath) for astr in alist: strategyList = astr.strip().split(",") if len(strategyList) < 2: continue if firstRecord: firstRecord = False self.strategy_id.text = strategyList[0] self.strategyDict[strategyList[0]] = strategyList abtn = SButton(text=strategyList[0]) abtn.size_hint_y = None abtn.height = 30 abtn.bind(on_release=self.strategyDropDown.select) self.strategyDropDown.add_widget(abtn) self.strategy_id.bind(on_release=self.strategyDropDown.open) self.strategyDropDown.bind(on_select=self.strategySelect) self.savefile_id.bind(focus=self.onSavefileFocus) def onRowdataFocus(self, instance, value): if value: content = SFileSelectDialog(load=self.loadRowdataDir, cancel=self.dismiss_rowdataPopup) content.filechooser_id.path = rowdata_path popupTitle = self.sysConfDict.get("MSG_DOWNLOAD_FILE") self._rowdataPopup = SPopup(title=popupTitle, content=content, size_hint=(0.9, 0.9), title_font=CONSTS.FONT_NAME) self._rowdataPopup.open() def dismiss_rowdataPopup(self): self._rowdataPopup.dismiss() def loadRowdataDir(self, path, filename): if len(filename) == 0: self.app.showErrorView(True, CONSTS.ERR_UNSELECT_FILE) return self._rowdataPopup.dismiss() rowdata_path = path filenameTmp = filename[0][len(path) + 1:] self.rowdata_id.text = filenameTmp filePath = os.path.join(os.path.dirname(__file__), ".." + os.sep + "conf" + os.sep + "user.ini") userConf = sutil.getDictFromFile(filePath) userConf["ROWDATA_DIR"] = path with open(filePath, 'w', encoding = 'utf-8') as f: for key in userConf.keys(): value = userConf.get(key) aStr = key + "=" + value + "\n" f.write(aStr) def strategySelect(self, instance, atext): self.strategy_id.text = atext.text def onSavefileFocus(self, instance, value): if value: content = SFileInputDialog(load=self.loadSavefileDir, cancel=self.dismiss_savefilePopup) content.filechooser_id.path = data_path popupTitle = self.sysConfDict.get("MSG_DOWNLOAD_FILE") self._savefilePopup = SPopup(title=popupTitle, content=content, size_hint=(0.9, 0.9), title_font=CONSTS.FONT_NAME) self._savefilePopup.open() def dismiss_savefilePopup(self): self._savefilePopup.dismiss() def loadSavefileDir(self, path, filename): if len(filename) == 0: self.app.showErrorView(True, CONSTS.ERR_UNSELECT_FILE) return self._savefilePopup.dismiss() data_path = path self.savefile_id.text = filename filePath = os.path.join(os.path.dirname(__file__), ".." + os.sep + "conf" + os.sep + "user.ini") userConf = sutil.getDictFromFile(filePath) userConf["BACKTEST_SELECT_DIR"] = path[0:path.rfind(os.sep)] userConf["BACKTEST_DIR"] = path with open(filePath, 'w', encoding = 'utf-8') as f: for key in userConf.keys(): value = userConf.get(key) aStr = key + "=" + value + "\n" f.write(aStr)
class SBTMenu(BoxLayout): body_layout = ObjectProperty(None) exitLayout_id = ObjectProperty(None) sbacktest = None fileList = None app = None confDict = {} filePath = os.path.join(os.path.dirname(__file__), ".." + os.sep + "conf" + os.sep + "msgcode.ini") confDict[CONSTS.MSG_CODE_DICT] = sutil.getDictFromFile(filePath) filePath = os.path.join(os.path.dirname(__file__), ".." + os.sep + "conf" + os.sep + "sysconf_zh_tw.ini") confDict[CONSTS.SYS_CONF_DICT] = sutil.getDictFromFile(filePath) def __init__(self, paramDict, **kwargs): super(SBTMenu, self).__init__(**kwargs) self.paramDict = paramDict self.app = self.paramDict.get(CONSTS.S_APP) userConf = sutil.getDictFromFile(os.path.join(os.path.dirname(__file__), ".." + os.sep + "conf" + os.sep + "user.ini")) bt_file = userConf.get("BACKTEST_FILE") if bt_file != None and bt_file != "": self.fileList = bt_file.split(",") aflag = False for afile in self.fileList: afilePath = os.path.join(bk_file_dir, afile) if not os.path.exists(afilePath): aflag = True break if not aflag: if self.body_layout != None: self.remove_widget(self.body_layout) refDict = {} for key in self.paramDict.keys(): refDict[key] = self.paramDict[key] refDict["fileDir"] = bk_file_dir refDict["fileList"] = self.fileList refDict[CONSTS.S_BTMENU] = self self.sbacktest = SBacktest(refDict) self.body_layout = self.sbacktest self.body_layout.size_hint = (1, .95) self.body_layout.pos_hint = {'x':0,'y':0} self.add_widget(self.body_layout, index=0) subMenu = self.paramDict.get("SUBMENU") if subMenu != None: if subMenu == False: exitBtn = SButton(text="離開", size_hint=(1, 1)) exitBtn.halign = "center" exitBtn.valign = "middle" exitBtn.bind(on_release=self.closeWindows) self.exitLayout_id.add_widget(exitBtn) def closeWindows(self, obj): if self.app != None: self.app.closeWindows() def stradeCost(self): self.stcLayout = STradeCost({CONSTS.S_APP:self.app}) popup = SPopup(title="交易成本設定", content=self.stcLayout, size_hint=(None, None), size=(640, 480), auto_dismiss=False) self.stcLayout.closebtn_id.bind(on_press=popup.dismiss) popup.title_font = CONSTS.FONT_NAME popup.open() def sselectFile(self): self.ssfLayout = SSelectFile({CONSTS.S_APP:self.app}) self.ssf_popup = SPopup(title="選擇回測檔案", content=self.ssfLayout, size_hint=(None, None), size=(540, 480), auto_dismiss=False) self.ssfLayout.ensurebtn_id.bind(on_press=self.finishedSelectFiles) self.ssfLayout.closebtn_id.bind(on_press=self.ssf_popup.dismiss) self.ssf_popup.title_font = CONSTS.FONT_NAME self.ssf_popup.open() def finishedSelectFiles(self, instance): fileCount = len(self.ssfLayout.rightrv_id.data) if fileCount == 0: self.app.showErrorView(True, CONSTS.ERR_UNSELECT_FILE) return self.ssf_popup.dismiss() self.saveUserConf() if self.fileList != None: self.fileList.clear() else: self.fileList = [] for adict in self.ssfLayout.rightrv_id.data: self.fileList.append(adict.get("text")) if self.sbacktest == None: self.remove_widget(self.body_layout) refDict = {} for key in self.paramDict.keys(): refDict[key] = self.paramDict[key] refDict["fileDir"] = self.ssfLayout.filepath refDict["fileList"] = self.fileList refDict[CONSTS.S_BTMENU] = self self.sbacktest = SBacktest(refDict) self.body_layout = self.sbacktest self.body_layout.size_hint = (1, .96) self.body_layout.pos_hint = {'x':0,'y':0} self.add_widget(self.body_layout, index=0) else: self.sbacktest.loadFile(self.ssfLayout.filepath, self.fileList) def saveUserConf(self): filePath = os.path.join(os.path.dirname(__file__), "../conf/user.ini") userConf = sutil.getDictFromFile(filePath) userConf["BACKTEST_SELECT_DIR"] = self.ssfLayout.filedir userConf["BACKTEST_DIR"] = self.ssfLayout.filepath backtest_file = "" for adict in self.ssfLayout.rightrv_id.data: backtest_file += adict.get("text") backtest_file += "," backtest_file = backtest_file[0:-1] userConf["BACKTEST_FILE"] = backtest_file with open(filePath, 'w', encoding = 'utf-8') as f: for key in userConf.keys(): value = userConf.get(key) aStr = key + "=" + value + "\n" f.write(aStr) def analyzeBacktest(self): if self.sbacktest != None: if self.sbacktest.dataList != None and len(self.sbacktest.dataList) != 0: refDict = {} for key in self.paramDict.keys(): refDict[key] = self.paramDict.get(key) refDict["dataList"] = self.sbacktest.dataList refDict["fileList"] = self.fileList refDict[CONSTS.S_BTMENU] = self self.strLayout = STradeReport(refDict) self.str_popup = SPopup(title="分析報表", content=self.strLayout, size_hint=(None, None), size=(800, 600), auto_dismiss=False) self.strLayout.closebtn_id.bind(on_press=self.str_popup.dismiss) self.str_popup.title_font = CONSTS.FONT_NAME self.str_popup.open() else: self.app.showErrorView(True, CONSTS.ERR_NO_BACKTEST_DATA) else: self.app.showErrorView(True, CONSTS.ERR_NOT_EXECUTE_BACKTEST)
class SUniteMenu(FloatLayout): menuId = ObjectProperty(None) body_layout = ObjectProperty(None) content_layout = ObjectProperty(None) btMenu = ObjectProperty(None) app = None menuLayout = ObjectProperty(None) sosLayout = None sosPopup = None sbacktest = None selfStkQuote = None sselectStock = None fileList = None def __init__(self, paramDict, **kwargs): super(SUniteMenu, self).__init__(**kwargs) self.paramDict = paramDict self.app = self.paramDict.get(CONSTS.S_APP) self.menuId.add_widget(BoxLayout(size_hint=(.01, 1))) mbtn = MenuButton(suniteMenu=self, text="用戶中心", size_hint=(.15, 1), halign="center", valign="middle") self.menuId.add_widget(mbtn) self.menuId.add_widget(BoxLayout(size_hint=(.01, 1))) mbtn = MenuButton(suniteMenu=self, text="交易執行", size_hint=(.15, 1), halign="center", valign="middle") self.menuId.add_widget(mbtn) self.menuId.add_widget(BoxLayout(size_hint=(.01, 1))) mbtn = MenuButton(suniteMenu=self, text="交易分析", size_hint=(.15, 1), halign="center", valign="middle") self.menuId.add_widget(mbtn) self.menuId.add_widget(BoxLayout(size_hint=(.01, 1))) mbtn = MenuButton(suniteMenu=self, text="智慧選股", size_hint=(.15, 1), halign="center", valign="middle") mbtn.bind(on_release=self.optionSelect) self.menuId.add_widget(mbtn) self.menuId.add_widget(BoxLayout(size_hint=(.01, 1))) mbtn = MenuButton(suniteMenu=self, text="股票報價", size_hint=(.15, 1), halign="center", valign="middle") mbtn.bind(on_release=self.stockQuote) self.menuId.add_widget(mbtn) self.menuId.add_widget(BoxLayout(size_hint=(.01, 1))) mbtn = MenuButton(suniteMenu=self, text="離開", size_hint=(.15, 1), halign="center", valign="middle") mbtn.bind(on_release=self.closeWindows) self.menuId.add_widget(mbtn) self.menuId.add_widget(BoxLayout(size_hint=(.04, 1))) def closeWindows(self, instance): if self.app != None: self.app.closeWindows() def login(self, execType): self.execType = execType self.loginLayout = SLogin({CONSTS.S_APP: self.app}) self.loginPopup = Popup(title="登入", content=self.loginLayout, size_hint=(None, None), size=(400, 300), auto_dismiss=False) self.loginLayout.closebtn_id.bind(on_press=self.loginPopup.dismiss) self.loginLayout.loginbtn_id.bind(on_press=self.loginProcess) self.loginPopup.title_font = CONSTS.FONT_NAME self.loginPopup.open() def loginProcess(self, instance): Clock.schedule_once(self.loginSchedule) def loginSchedule(self, instance): self.event = Clock.schedule_interval(self.loginCheck, .0005) threading.Thread(target=self.toolkitLogin).start() def loginCheck(self, dt): if self.loginLayout.loginFlag != None: self.event.cancel() if self.loginLayout.loginFlag == True: self.app.loginFlag = True self.app.accountIdList = self.loginLayout.accountIdList self.app.account = self.loginLayout.user_id.text self.app.pwd = self.loginLayout.pwd_id.text self.loginPopup.dismiss() if self.execType == "query": self.openWebBrowser() elif self.execType == "download": self.downloadData() elif self.execType == "optionSelect": self.doOptionSelect() elif self.execType == "stockQuote": self.doStockQuote() def toolkitLogin(self): self.loginLayout.login() def removeMenu(self): if self.menuLayout == None: return self.remove_widget(self.menuLayout) def userMenu(self, instance): width = instance.size[0] + 10 x1 = instance.pos[0] y1 = instance.pos[1] - 63 self.menuLayout = MenuLayout(suniteMenu=self, size_hint=(None, None), size=(width, instance.size[1]), pos=[x1, y1], orientation="vertical") self.menuLayout.add_widget(BoxLayout(size_hint=(1, None), height=1)) btn = SubMenuButton(size_hint=(1, None), height=30, text="用戶註冊") btn.bind(on_press=self.registerUser) self.menuLayout.add_widget(btn) self.menuLayout.add_widget(BoxLayout(size_hint=(1, None), height=1)) btn = SubMenuButton(size_hint=(1, None), height=30, text="帳務查詢") btn.bind(on_press=self.query) self.menuLayout.add_widget(btn) self.menuLayout.add_widget(BoxLayout(size_hint=(1, None), height=1)) self.add_widget(self.menuLayout) self.menuLayout.layoutHeight = 63 return self.menuLayout def registerUser(self, instance): self.removeMenu() aDict = sutil.getDictFromFile( os.path.join(os.path.dirname(__file__), ".." + os.sep + "conf" + os.sep + "user.ini")) webbrowser.open(aDict.get("WEB_REGISTER_URL")) def query(self, instance): self.removeMenu() if self.app.loginFlag == False: self.login("query") else: self.openWebBrowser() def openWebBrowser(self): urlParam = "dataID=" + self.app.account + "&dataCheck=" + self.app.pwd aDict = sutil.getDictFromFile( os.path.join(os.path.dirname(__file__), ".." + os.sep + "conf" + os.sep + "user.ini")) webbrowser.open(aDict.get("WEB_LOGIN_URL") + urlParam, new=0) def executeMenu(self, instance): width = instance.size[0] + 40 x1 = instance.pos[0] y1 = instance.pos[1] - 125 self.menuLayout = MenuLayout(suniteMenu=self, size_hint=(None, None), size=(width, instance.size[1]), pos=[x1, y1], orientation="vertical") self.menuLayout.add_widget(BoxLayout(size_hint=(1, None), height=1)) btn = SubMenuButton(size_hint=(1, None), height=30, text="歷史報價下載") btn.bind(on_press=self.downloadProcess) self.menuLayout.add_widget(btn) self.menuLayout.add_widget(BoxLayout(size_hint=(1, None), height=1)) btn = SubMenuButton(size_hint=(1, None), height=30, text="ABXToolkit使用說明") btn.bind(on_press=self.explain) self.menuLayout.add_widget(btn) self.menuLayout.add_widget(BoxLayout(size_hint=(1, None), height=1)) btn = SubMenuButton(size_hint=(1, None), height=30, text="交易策略設定") btn.bind(on_press=self.strategySetting) self.menuLayout.add_widget(btn) self.menuLayout.add_widget(BoxLayout(size_hint=(1, None), height=1)) btn = SubMenuButton(size_hint=(1, None), height=30, text="執行交易程式") btn.bind(on_press=self.executeTrade) self.menuLayout.add_widget(btn) self.menuLayout.add_widget(BoxLayout(size_hint=(1, None), height=1)) self.add_widget(self.menuLayout) self.menuLayout.layoutHeight = 125 return self.menuLayout def downloadProcess(self, instance): self.removeMenu() if self.app.loginFlag == False: self.login("download") else: self.downloadData() def downloadData(self): downloadLayout = SDownload({CONSTS.S_APP: self.app}) popup = SPopup(title="下載歷史報價資料", content=downloadLayout, size_hint=(None, None), size=(540, 400), auto_dismiss=False) downloadLayout.closebtn_id.bind(on_press=popup.dismiss) popup.title_font = CONSTS.FONT_NAME popup.open() def explain(self, instance): self.removeMenu() aDict = sutil.getDictFromFile( os.path.join(os.path.dirname(__file__), ".." + os.sep + "conf" + os.sep + "user.ini")) webbrowser.open(aDict.get("WEB_EXPLAIN_URL"), new=0) def strategySetting(self, instance): self.removeMenu() self.ssyLayout = SStrategy({CONSTS.S_APP: self.app}) popup = SPopup(title="交易策略設定", content=self.ssyLayout, size_hint=(None, None), size=(640, 480), auto_dismiss=False) self.ssyLayout.closebtn_id.bind(on_press=popup.dismiss) popup.title_font = CONSTS.FONT_NAME popup.open() def executeTrade(self, instance): self.removeMenu() self.etLayout = SExecTrade({CONSTS.S_APP: self.app}) self.et_popup = SPopup(title="執行交易程式", content=self.etLayout, size_hint=(None, None), size=(360, 280), auto_dismiss=False) self.etLayout.ensurebtn_id.bind(on_press=self.execTradeEvent) self.etLayout.closebtn_id.bind(on_press=self.et_popup.dismiss) self.et_popup.title_font = CONSTS.FONT_NAME self.et_popup.open() def execTradeEvent(self, instance): rowdataName = self.etLayout.rowdata_id.text strategyName = self.etLayout.strategy_id.text savefileName = self.etLayout.savefile_id.text if rowdataName == "": self.app.showErrorView(True, CONSTS.ERR_UNSELECT_HISTORY_DATA) return elif strategyName == "": self.app.showErrorView(True, CONSTS.ERR_UNSELECT_STRATEGY) return elif savefileName == "": self.app.showErrorView(True, CONSTS.ERR_UNSELECT_SAVEFILE) return strategy_dir = os.path.abspath( os.path.join(os.path.dirname(__file__), ".." + os.sep + "conf" + os.sep + "strategy")) strategyData = None if strategyName != "": alist = sutil.getListFromFile( os.path.join(os.path.dirname(__file__), ".." + os.sep + "conf" + os.sep + "strategy.ini")) for astr in alist: strategyList = astr.strip().split(",") if len(strategyList) < 2: continue if strategyName == strategyList[0]: strategyData = strategyList[1] isExistFlag = True if strategyData != None: filePath = os.path.join(strategy_dir, strategyData) if os.path.exists(filePath) != True: isExistFlag = False else: isExistFlag = False if isExistFlag == False: msgCodeDict = self.app.confDict.get(CONSTS.MSG_CODE_DICT) msgText = msgCodeDict.get(CONSTS.ERR_STRATEGY_FILE_NOT_FOUND) self.app.showErrorView(False, strategyName, msgText) return userConf = sutil.getDictFromFile( os.path.join(os.path.dirname(__file__), ".." + os.sep + "conf" + os.sep + "user.ini")) rowdata_dir = userConf.get("ROWDATA_DIR") data_dir = userConf.get("BACKTEST_DIR") self.rowdata_file = os.path.join(rowdata_dir, rowdataName) self.strategy_file = os.path.join(strategy_dir, strategyData) self.savefile_file = os.path.join(data_dir, savefileName) self.doPtradeEvent() def doPtradeEvent(self): contentLayout = BoxLayout() contentLayout.orientation = "vertical" contentLayout.size_hint = (1, 1) contentLabel = SLabel(text=" 交易執行中...", size_hint=(1, .8)) contentLayout.add_widget(contentLabel) sysConfDict = self.app.confDict.get(CONSTS.SYS_CONF_DICT) self.result = None self.dp_popup = Popup(title=sysConfDict.get("MSG_TITLE"), content=contentLayout, size_hint=(None, None), size=(160, 120), auto_dismiss=False) self.dp_popup.title_font = CONSTS.FONT_NAME self.dp_popup.bind(on_open=self.dp_open) Clock.schedule_once(self.doPtradeStart) def doPtradeStart(self, instance): self.dp_popup.open() threading.Thread(target=self.toolkitPtrade).start() def toolkitPtrade(self): self.result = abxtoolkit.do_ptrade(self.rowdata_file, self.strategy_file, self.savefile_file) def doPtrade_check(self, dt): if self.result != None: self.dp_popup.dismiss() self.event.cancel() errCode = self.result.get("ErrCode") if errCode != 0: errDesc = self.result.get("ErrDesc") self.app.showErrorView(False, errCode, errDesc) else: self.finishedPopup() def dp_open(self, instance): self.event = Clock.schedule_interval(self.doPtrade_check, .0005) def finishedPopup(self): content = BoxLayout(size_hint=(1, 1), orientation="vertical") content.add_widget(BoxLayout(size_hint=(1, .4))) bottomLayout = BoxLayout(size_hint=(1, .2), orientation="horizontal") bottomLayout.add_widget(BoxLayout(size_hint=(.1, 1))) ensurebtn = SButton(text="確定", size_hint=(.8, .8)) bottomLayout.add_widget(ensurebtn) bottomLayout.add_widget(BoxLayout(size_hint=(.1, 1))) content.add_widget(bottomLayout) content.add_widget(BoxLayout(size_hint=(1, .4))) self.fin_popup = SPopup(title="執行完成", content=content, title_font=CONSTS.FONT_NAME, size_hint=(None, None), size=(200, 100), auto_dismiss=False) ensurebtn.bind(on_press=self.fin_popup.dismiss) self.fin_popup.open() def analyzeMenu(self, instance): width = instance.size[0] + 10 x1 = instance.pos[0] y1 = instance.pos[1] - 94 self.menuLayout = MenuLayout(suniteMenu=self, size_hint=(None, None), size=(width, instance.size[1]), pos=[x1, y1], orientation="vertical") self.menuLayout.add_widget(BoxLayout(size_hint=(1, None), height=1)) btn = SubMenuButton(size_hint=(1, None), height=30, text="回測") btn.bind(on_press=self.sselectFile) self.menuLayout.add_widget(btn) self.menuLayout.add_widget(BoxLayout(size_hint=(1, None), height=1)) btn = SubMenuButton(size_hint=(1, None), height=30, text="交易分析") btn.bind(on_press=self.analyzeBacktest) self.menuLayout.add_widget(btn) self.menuLayout.add_widget(BoxLayout(size_hint=(1, None), height=1)) btn = SubMenuButton(size_hint=(1, None), height=30, text="交易成本設定") btn.bind(on_press=self.stradeCost) self.menuLayout.add_widget(btn) self.menuLayout.add_widget(BoxLayout(size_hint=(1, None), height=1)) self.add_widget(self.menuLayout) self.menuLayout.layoutHeight = 94 return self.menuLayout def sselectFile(self, instance): self.removeMenu() self.ssfLayout = SSelectFile({CONSTS.S_APP: self.app}) self.ssf_popup = SPopup(title="選擇回測檔案", content=self.ssfLayout, size_hint=(None, None), size=(540, 480), auto_dismiss=False) self.ssfLayout.ensurebtn_id.bind(on_press=self.finishedSelectFiles) self.ssfLayout.closebtn_id.bind(on_press=self.ssf_popup.dismiss) self.ssf_popup.title_font = CONSTS.FONT_NAME self.ssf_popup.open() def finishedSelectFiles(self, instance): fileCount = len(self.ssfLayout.rightrv_id.data) if fileCount == 0: self.app.showErrorView(True, CONSTS.ERR_UNSELECT_FILE) return self.ssf_popup.dismiss() self.saveUserConf() if self.selfStkQuote != None: self.selfStkQuote.closeStkQuote() if self.fileList != None: self.fileList.clear() else: self.fileList = [] for adict in self.ssfLayout.rightrv_id.data: self.fileList.append(adict.get("text")) if self.sbacktest == None: self.body_layout.remove_widget(self.content_layout) refDict = {} for key in self.paramDict.keys(): refDict[key] = self.paramDict[key] refDict["fileDir"] = self.ssfLayout.filepath refDict["fileList"] = self.fileList self.sbacktest = SBacktest(refDict) self.content_layout = self.sbacktest self.content_layout.size_hint = (1, 1) self.body_layout.add_widget(self.content_layout) else: self.sbacktest.loadFile(self.ssfLayout.filepath, self.fileList) """if self.sbacktest == None: self.body_layout.remove_widget(self.content_layout) refDict = {} for key in self.paramDict.keys(): refDict[key] = self.paramDict[key] refDict["fileDir"] = self.ssfLayout.filepath refDict["fileList"] = self.fileList self.sbacktest = SBacktest(refDict) self.content_layout = self.sbacktest self.content_layout.size_hint = (1, 1) self.body_layout.add_widget(self.content_layout) else: self.sbacktest.loadFile(self.ssfLayout.filepath, self.fileList) """ self.body_layout.remove_widget(self.content_layout) refDict = {} for key in self.paramDict.keys(): refDict[key] = self.paramDict[key] refDict["fileDir"] = self.ssfLayout.filepath refDict["fileList"] = self.fileList self.sbacktest = SBacktest(refDict) self.content_layout = self.sbacktest self.content_layout.size_hint = (1, 1) self.body_layout.add_widget(self.content_layout) def saveUserConf(self): filePath = os.path.join(os.path.dirname(__file__), ".." + os.sep + "conf" + os.sep + "user.ini") userConf = sutil.getDictFromFile(filePath) userConf["BACKTEST_SELECT_DIR"] = self.ssfLayout.filedir userConf["BACKTEST_DIR"] = self.ssfLayout.filepath backtest_file = "" for adict in self.ssfLayout.rightrv_id.data: backtest_file += adict.get("text") backtest_file += "," backtest_file = backtest_file[0:-1] userConf["BACKTEST_FILE"] = backtest_file with open(filePath, 'w', encoding='utf-8') as f: for key in userConf.keys(): value = userConf.get(key) aStr = key + "=" + value + "\n" f.write(aStr) def analyzeBacktest(self, instance): self.removeMenu() if self.sbacktest != None: if self.sbacktest.dataList != None and len( self.sbacktest.dataList) != 0: refDict = {} for key in self.paramDict.keys(): refDict[key] = self.paramDict.get(key) refDict["dataList"] = self.sbacktest.dataList refDict["fileList"] = self.fileList refDict[CONSTS.S_BTMENU] = self self.strLayout = STradeReport(refDict) self.str_popup = SPopup(title="分析報表", content=self.strLayout, size_hint=(None, None), size=(800, 600), auto_dismiss=False) self.strLayout.closebtn_id.bind( on_press=self.str_popup.dismiss) self.str_popup.title_font = CONSTS.FONT_NAME self.str_popup.open() else: self.app.showErrorView(True, CONSTS.ERR_NO_BACKTEST_DATA) else: self.app.showErrorView(True, CONSTS.ERR_NOT_EXECUTE_BACKTEST) def stradeCost(self, instance): self.removeMenu() self.stcLayout = STradeCost({CONSTS.S_APP: self.app}) popup = SPopup(title="交易成本設定", content=self.stcLayout, size_hint=(None, None), size=(640, 480), auto_dismiss=False) self.stcLayout.closebtn_id.bind(on_press=popup.dismiss) popup.title_font = CONSTS.FONT_NAME popup.open() def optionSelect(self, instance): if self.app.loginFlag == False: self.login("optionSelect") else: self.doOptionSelect() def doOptionSelect(self): if self.sosLayout == None: self.sosLayout = SOptionSelect({CONSTS.S_APP: self.app}) else: self.sosPopup.open() return self.sosPopup = SPopup(title="智慧選股", content=self.sosLayout, size_hint=(None, None), size=(640, 480), auto_dismiss=False) self.sosLayout.ensurebtn_id.bind(on_press=self.execOptionResult) self.sosLayout.resetbtn_id.bind(on_press=self.resetOptionSelect) self.sosLayout.selectbtn_id.bind(on_press=self.showOptionSelect) self.sosLayout.closebtn_id.bind(on_press=self.optionPopupDismiss) self.sosPopup.title_font = CONSTS.FONT_NAME self.sosPopup.open() def execOptionResult(self, instance): if self.sosLayout.optionList == None: self.app.showErrorView(True, CONSTS.ERR_UNSELECT_OPTION) return else: isSelectFlag = False for aObj in self.sosLayout.optionList: if aObj.isSelected(): isSelectFlag = True break if isSelectFlag == False: self.app.showErrorView(True, CONSTS.ERR_UNSELECT_OPTION) return self.optionPopupDismiss(instance) fidList = [] for aObj in self.sosLayout.optionList: if aObj.isSelected(): fidList.append(aObj.getValueDict()) self.body_layout.remove_widget(self.content_layout) refDict = {} for key in self.paramDict.keys(): refDict[key] = self.paramDict[key] refDict["fidList"] = fidList self.sselectStock = SSelectStock(refDict) self.content_layout = self.sselectStock self.content_layout.size_hint = (1, 1) self.body_layout.add_widget(self.content_layout) def resetOptionSelect(self, instance): self.sosLayout.setToOptionDefault() def showOptionSelect(self, instance): if self.sosLayout.optionList == None: self.app.showErrorView(True, CONSTS.ERR_UNSELECT_OPTION) return else: isSelectFlag = False for aObj in self.sosLayout.optionList: if aObj.isSelected(): isSelectFlag = True break if isSelectFlag == False: self.app.showErrorView(True, CONSTS.ERR_UNSELECT_OPTION) return self.sosLayout.showSelectedOptionDesc() def optionPopupDismiss(self, instance): self.sosPopup.dismiss() def stockQuote(self, instance): self.removeMenu() if self.app.loginFlag == False: self.login("stockQuote") else: self.doStockQuote() def doStockQuote(self): self.body_layout.remove_widget(self.content_layout) refDict = {} for key in self.paramDict.keys(): refDict[key] = self.paramDict[key] self.selfStkQuote = SelfStkQuote(refDict) self.content_layout = self.selfStkQuote self.content_layout.size_hint = (1, 1) self.body_layout.add_widget(self.content_layout)