def doSelectStock(self): userConf = sutil.getDictFromFile(os.path.join(os.path.dirname(__file__), ".." + os.sep + "conf" + os.sep + "user.ini")) useridTxt = self.app.account if useridTxt.find("@") != -1: useridTxt = "1|" + useridTxt else: useridTxt = "2|" + useridTxt gwParam = {} gwParam["Host"] = userConf.get("DOWNLOAD_URL").strip() gwParam["Port"] = int(userConf.get("DOWNLOAD_PORT").strip()) gwParam["User"] = useridTxt gwParam["Password"] = self.app.pwd gwParam["ProductId"] = int(userConf.get("PRODUCT_ID").strip()) gwParam["UserType"] = int(userConf.get("USER_TYPE").strip()) gwParam["LoginType"] = int(userConf.get("TRADE_LOGIN_TYPE").strip()) gwParam["Source"] = "" gwParam["StockCount"] = 0 gwParam["Condition"] = self.fidList 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.select_stock refParam["ResultFunc"] = self._finishedSelectStock sgwPopup = SGwPopup(refParam) sgwPopup.processEvent()
def _doQueryFormulaId(self): refParam = {} refParam["CONSTS.S_APP"] = self.app refParam["TitleMsg"] = self.sysConfDict.get("MSG_TITLE") refParam["InfoMsg"] = " 資料讀取中..." refParam["PopupSize"] = (160, 120) gwParam = {} userConf = sutil.getDictFromFile(os.path.join(os.path.dirname(__file__), ".." + os.sep + "conf" + os.sep + "user.ini")) useridTxt = self.app.account if useridTxt.find("@") != -1: useridTxt = "1|" + useridTxt else: useridTxt = "2|" + useridTxt gwParam["Host"] = userConf.get("DOWNLOAD_URL").strip() gwParam["Port"] = int(userConf.get("DOWNLOAD_PORT").strip()) gwParam["User"] = useridTxt gwParam["Password"] = self.app.pwd gwParam["ProductId"] = int(userConf.get("PRODUCT_ID").strip()) gwParam["UserType"] = int(userConf.get("USER_TYPE").strip()) gwParam["LoginType"] = int(userConf.get("TRADE_LOGIN_TYPE").strip()) gwParam["CateID"] = 8202000 refParam["GwParam"] = gwParam refParam["GwFunc"] = abxtoolkit.query_formulaid refParam["ResultFunc"] = self._finishedQueryFormulaId sgwPopup = SGwPopup(refParam) sgwPopup.processEvent()
def initial_data(self): filePath = os.path.join(os.path.dirname(__file__), "../conf/user.ini") self.userConf = sutil.getDictFromFile(filePath) account = self.userConf.get("ACCOUNT") password = self.userConf.get("PASSWORD") if account != None and account != "": self.user_id.text = account self.saveuser_id.active = True self.pwd_id.text = password
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 saveUserConf(self): filePath = os.path.join(os.path.dirname(__file__), "../conf/user.ini") userConf = sutil.getDictFromFile(filePath) if self.saveuser_id.active: userConf["ACCOUNT"] = self.user_id.text userConf["PASSWORD"] = self.pwd_id.text else: userConf["ACCOUNT"] = "" userConf["PASSWORD"] = "" 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 __init__(self, paramDict, **kwargs): super(STradeGraph, self).__init__(**kwargs) self.paramDict = paramDict self.btmenu = self.paramDict.get(CONSTS.S_BTMENU) self.dataList = self.paramDict.get("dataList") # 1001-Start: 計算最大及最小獲利率 self.min_profitPer = 0 self.max_profitPer = 0 tmpProfitPer = None if self.dataList != None and len(self.dataList) != 0: for profitPer in self.dataList: if profitPer < 0: tmpProfitPer = math.floor(profitPer) else: tmpProfitPer = math.ceil(profitPer) if tmpProfitPer > self.max_profitPer: self.max_profitPer = tmpProfitPer if tmpProfitPer < self.min_profitPer: self.min_profitPer = tmpProfitPer self.min_profitPer = int(self.min_profitPer) self.max_profitPer = int(self.max_profitPer) # 1001-End. self.maxNum = 5 self.yscale = 1 tradeGraphDict = sutil.getDictFromFile(os.path.join(os.path.dirname(__file__), ".." + os.sep + "conf" + os.sep + "trade_graph.ini")) self.shift_left = int(tradeGraphDict.get("SHIFT_LEFT")) self.shift_right = int(tradeGraphDict.get("SHIFT_RIGHT")) self.shift_bottom = int(tradeGraphDict.get("SHIFT_BOTTOM")) self.shift_top = int(tradeGraphDict.get("SHIFT_TOP")) self.ycordWidth = int(tradeGraphDict.get("YCORD_WIDTH")) self.pillarPoint = int(tradeGraphDict.get("PILLAR_POINT")) self.pillarGapPoint = int(tradeGraphDict.get("PILLAR_GAP_POINT")) self.pillarSumPoint = self.pillarPoint + self.pillarGapPoint self.FRAME_COLOR = colorHex(tradeGraphDict.get("FRAME_COLOR")) self.GRID_COLOR = colorHex(tradeGraphDict.get("GRID_COLOR")) self.CORD_INFO_COLOR = colorHex(tradeGraphDict.get("CORD_INFO_COLOR")) self.CROSS_LINE_COLOR = colorHex(tradeGraphDict.get("CROSS_LINE_COLOR")) self.TRADE_INFO_FGCOLOR = colorHex(tradeGraphDict.get("TRADE_INFO_FGCOLOR")) self.info_tradeNum = SLabel(text="") #交易次數 self.info_tradeNum.color = self.TRADE_INFO_FGCOLOR self.info_profitPer = SLabel(text="") #獲利率 self.info_profitPer.color = self.TRADE_INFO_FGCOLOR self.bind(pos=self.charting) self.bind(size=self.charting) Window.bind(mouse_pos=self.mousePos)
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 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 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)
def __init__(self, paramDict, **kwargs): super(SbtGraph, self).__init__(**kwargs) self.paramDict = paramDict self.btmenu = self.paramDict.get(CONSTS.S_BTMENU) trendGraphDict = sutil.getDictFromFile(os.path.join(os.path.dirname(__file__), ".." + os.sep + "conf" + os.sep + "trend_graph.ini")) self.MAX_NUM_PER_PAGE = int(trendGraphDict.get("MAX_NUM_PER_PAGE")) self.MIN_NUM_PER_PAGE = int(trendGraphDict.get("MIN_NUM_PER_PAGE")) self.UP_DOWN_NUM = int(trendGraphDict.get("UP_DOWN_NUM")) self.num_per_page = int(trendGraphDict.get("DEFAULT_NUM_PER_PAGE")) self.dataList = self.paramDict.get("datalist") self.fileList = self.paramDict.get("fileList") self.data_num = len(self.dataList) self.firstFlag = True self.calcPageInfo() self.page_id.bind(on_text_validate=self.on_page_id_enter) self.bt_file_id.text = "[b]" + self.fileList[0] + "[/b]"
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)
class SUniteApp(App): suMenu = ObjectProperty(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) loginFlag = False account = "" pwd = "" accountIdList = [] stkNameDict = {} def build(self): self.suMenu = SUniteMenu({CONSTS.S_APP: self}) return self.suMenu def closeWindows(self): self.get_running_app().stop() def showErrorView(self, isGetMsgDesc, msgCode, msgDesc=None): contentLayout = BoxLayout() contentLayout.orientation = "vertical" contentLayout.size_hint = (1, 1) if isGetMsgDesc == True: msgCodeDict = self.confDict.get(CONSTS.MSG_CODE_DICT) msgText = msgCodeDict.get(msgCode) if msgText == None: msgText = "Unknow error code->" + str(msgCode) else: msgText = str(msgCode) + "->" + msgText if msgDesc == None or msgDesc == "": contentLabel = SLabel(text=msgText, size_hint=(1, .8)) contentLabel.halign = "center" contentLayout.add_widget(contentLabel) else: titleLabel = SLabel(text=msgText, size_hint=(1, .2)) titleLabel.halign = "center" contentLayout.add_widget(titleLabel) slview = ScrollView(size_hint=(1, .6)) contentLayout.add_widget(slview) explainLayout = STableGridLayout(cols=1, spacing=1, size_hint_y=None) explainLayout.bind( minimum_height=explainLayout.setter('height')) for aStr in msgDesc: explainLabel = SLabel(text=aStr, size_hint=(1, None), height=20) explainLabel.halign = "center" explainLabel.color = colorHex("#000000") explainLabel.font_name = CONSTS.FONT_NAME explainLayout.add_widget(explainLabel) slview.add_widget(explainLayout) else: msgText = str(msgCode) + "->" + msgDesc contentLabel = SLabel(text=msgText, size_hint=(1, .8)) contentLabel.halign = "center" contentLayout.add_widget(contentLabel) sysConfDict = self.confDict.get(CONSTS.SYS_CONF_DICT) contentBtn = SButton(text=sysConfDict.get("MSG_CONFIRM"), size_hint=(1, .2)) contentLayout.add_widget(contentBtn) popup = Popup(title=sysConfDict.get("MSG_TITLE"), content=contentLayout, size_hint=(None, None), size=(200, 200), auto_dismiss=False) contentBtn.bind(on_press=popup.dismiss) popup.title_font = CONSTS.FONT_NAME popup.open()
import win32timezone import kivy kivy.require('1.11.0') # replace with your current kivy version ! import sys import os sys.path.append( os.path.join(os.path.dirname(__file__), ".." + os.sep + "sbase" + os.sep)) sys.path.append( os.path.join(os.path.dirname(__file__), ".." + os.sep + "sbacktest" + os.sep)) import sutil aDict = sutil.getDictFromFile( os.path.join(os.path.dirname(__file__), ".." + os.sep + "conf" + os.sep + "user.ini")) backend_type = aDict.get("BACKEND_TYPE") if backend_type == None: backend_type = "glew" os.environ['KIVY_GL_BACKEND'] = backend_type from kivy.config import Config Config.set('kivy', 'exit_on_escape', '0') #設定esc鍵,不結束應用程式 Config.set('graphics', 'multisamples', '0') #設定部分電腦無法使用opengl的問題 Config.set('input', 'mouse', 'mouse,multitouch_on_demand') #消除點擊滑鼠右鍵會產生紅色圓點的問題 from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.uix.gridlayout import GridLayout from kivy.uix.scrollview import ScrollView
def __init__(self, paramDict, **kwargs): super(STrendChart, self).__init__(**kwargs) self.paramDict = paramDict self.app = self.paramDict.get(CONSTS.S_APP) self.stkId = self.paramDict.get("StkId") #股票id self.stkName = self.paramDict.get("StkName") #股票名稱 self.lastTradeDate = self.paramDict.get("LTD") #最後交易日 self.startTime = self.paramDict.get("StartTime") #起始時間 self.endTime = self.paramDict.get("EndTime") #截止時間 self.yesPrice = self.paramDict.get("YesPrice") #昨收價 self.decimal = self.paramDict.get("Decimal") #小數點位數 self.chartNum = sutil.calcTimeNum(int(self.startTime), int(self.endTime)) self.stkIdAndName.text = self.stkId[2:] + " " + self.stkName self.stkIdAndName.halign = "left" self.lastTradeDate_id.text = sutil.formatDate(self.lastTradeDate) refParam = {} for aKey in paramDict.keys(): refParam[aKey] = paramDict.get(aKey) trendGraphDict = sutil.getDictFromFile( os.path.join(os.path.dirname(__file__), ".." + os.sep + "conf" + os.sep + "strend_chart.ini")) self.shift_left = int(trendGraphDict.get("SHIFT_LEFT")) #圖形左邊位移距離 refParam["SHIFT_LEFT"] = self.shift_left refParam["SHIFT_GAPHEIGHT"] = int( trendGraphDict.get("SHIFT_GAPHEIGHT")) #價圖及量圖的間距 refParam["SHIFT_BOTTOM"] = int( trendGraphDict.get("SHIFT_BOTTOM")) #圖形底部位移距離 refParam["SHIFT_TOP"] = int(trendGraphDict.get("SHIFT_TOP")) #圖形上方位移距離 refParam["PRICE_HEIGHT_PER"] = int( trendGraphDict.get("PRICE_HEIGHT_PER")) #價圖高度佔比 refParam["VOLUME_HEIGHT_PER"] = int( trendGraphDict.get("VOLUME_HEIGHT_PER")) #量圖高度佔比 refParam["CORD_INFO_COLOR"] = colorHex( trendGraphDict.get("CORD_INFO_COLOR")) #座標資訊的文字顏色 refParam["DATA_INFO_COLOR"] = colorHex( trendGraphDict.get("DATA_INFO_COLOR")) #資訊的文字顏色 self.UP_COLOR = colorHex(trendGraphDict.get("UP_COLOR")) #上漲時線條顏色 self.DOWN_COLOR = colorHex(trendGraphDict.get("DOWN_COLOR")) #下跌時線條顏色 self.EQUAL_COLOR = colorHex( trendGraphDict.get("EQUAL_COLOR")) #持平時線條顏色 refParam["UP_COLOR"] = self.UP_COLOR refParam["DOWN_COLOR"] = self.DOWN_COLOR refParam["EQUAL_COLOR"] = self.EQUAL_COLOR refParam["VOLUME_COLOR"] = colorHex( trendGraphDict.get("VOLUME_COLOR")) #量的線條顏色 refParam["FRAME_COLOR"] = colorHex( trendGraphDict.get("FRAME_COLOR")) #邊框的線條顏色 refParam["GRID_COLOR"] = colorHex( trendGraphDict.get("GRID_COLOR")) #格線的線條顏色 refParam["CROSS_LINE_COLOR"] = colorHex( trendGraphDict.get("CROSS_LINE_COLOR")) #十字線線條顏色 refParam["UP_DOWN_PER"] = float( trendGraphDict.get("UP_DOWN_PER")) #漲跌幅度 refParam["InfoFunc"] = self.showInfo #顯示訊息的函式 refParam["ChartNum"] = self.chartNum #時間總筆數 refParam["Layout"] = self.body_layout refParam["Canvas"] = self.body_layout.canvas self.strendChart = SMinuteTimeChart(refParam) Clock.schedule_once(self.doQuoteStart, .5) #此段用意為讓畫面先顯示出來,再做後續的動作 self.bind(pos=self.charting) self.bind(size=self.charting) Window.bind(mouse_pos=self.mousePos)
def __init__(self, paramDict, **kwargs): super(STrendGraph, self).__init__(**kwargs) with self.canvas: Color(0, 20 / 255, 45 / 255) Rectangle(pos=self.pos, size=self.size) self.paramDict = paramDict self.btmenu = self.paramDict.get(CONSTS.S_BTMENU) self.tickNum = self.paramDict.get("ticknum") self.dataList = self.paramDict.get("datalist") if self.tickNum == 600: self.xgrid_num = 100 elif self.tickNum == 500: self.xgrid_num = 90 elif self.tickNum == 400: self.xgrid_num = 70 elif self.tickNum == 300: self.xgrid_num = 50 elif self.tickNum == 200: self.xgrid_num = 40 else: self.xgrid_num = 30 self.crossLineXIndex = -1 self.crossLineYIndex = -1 trendGraphDict = sutil.getDictFromFile( os.path.join(os.path.dirname(__file__), ".." + os.sep + "conf" + os.sep + "trend_graph.ini")) self.shift_left = int(trendGraphDict.get("SHIFT_LEFT")) self.shift_right = int(trendGraphDict.get("SHIFT_RIGHT")) self.shift_bottom = int(trendGraphDict.get("SHIFT_BOTTOM")) self.shift_top = int(trendGraphDict.get("SHIFT_TOP")) self.CORD_INFO_COLOR = colorHex(trendGraphDict.get("CORD_INFO_COLOR")) self.UP_COLOR = colorHex(trendGraphDict.get("UP_COLOR")) self.DOWN_COLOR = colorHex(trendGraphDict.get("DOWN_COLOR")) self.EQUAL_COLOR = colorHex(trendGraphDict.get("EQUAL_COLOR")) self.VOLUME_COLOR = colorHex(trendGraphDict.get("VOLUME_COLOR")) self.FRAME_COLOR = colorHex(trendGraphDict.get("FRAME_COLOR")) self.GRID_COLOR = colorHex(trendGraphDict.get("GRID_COLOR")) self.CROSS_LINE_COLOR = colorHex( trendGraphDict.get("CROSS_LINE_COLOR")) self.TRADEB_SIG_COLOR = colorHex( trendGraphDict.get("TRADEB_SIG_COLOR")) self.TRADES_SIG_COLOR = colorHex( trendGraphDict.get("TRADES_SIG_COLOR")) self.TRADE_INFO_FGCOLOR = colorHex( trendGraphDict.get("TRADE_INFO_FGCOLOR")) self.info_date = SLabel(text="") #日期 self.info_date.color = self.TRADE_INFO_FGCOLOR self.info_time = SLabel(text="") #時間 self.info_time.color = self.TRADE_INFO_FGCOLOR self.info_price = SLabel(text="") #成交價 self.info_price.color = self.TRADE_INFO_FGCOLOR self.info_vol = SLabel(text="") #成交量 self.info_vol.color = self.TRADE_INFO_FGCOLOR self.info_amt = SLabel(text="") #金額 self.info_amt.color = self.TRADE_INFO_FGCOLOR self.info_bs = SLabel(text="") #買賣訊號及買(賣)價 self.info_bs.color = self.TRADE_INFO_FGCOLOR self.calcMaxTick() self.bind(pos=self.charting) self.bind(size=self.charting) Window.bind(mouse_pos=self.mousePos)
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 __init__(self, paramDict, **kwargs): super(STechChart, self).__init__(**kwargs) self.mixedChartInfo_layout = SSysBoxLayout(size_hint=(1, .05), pos_hint={ 'x': 0, 'y': .29 }) self.add_widget(self.mixedChartInfo_layout) self.paramDict = paramDict self.app = self.paramDict.get(CONSTS.S_APP) self.stkId = self.paramDict.get("StkId") #股票id self.stkName = self.paramDict.get("StkName") #股票名稱 self.lastTradeDate = self.paramDict.get("LTD") #最後交易日 self.decimal = self.paramDict.get("Decimal") #小數點位數 self.idNameDate_id.text = self.stkId[ 2:] + " " + self.stkName + " " + sutil.formatDate( self.lastTradeDate) self.idNameDate_id.halign = "left" techChartDict = sutil.getDictFromFile( os.path.join(os.path.dirname(__file__), ".." + os.sep + "conf" + os.sep + "stech_chart.ini")) techChartParam = {} techChartParam["FRAME_COLOR"] = colorHex( techChartDict.get("FRAME_COLOR")) #邊框的線條顏色 techChartParam["GRID_COLOR"] = colorHex( techChartDict.get("GRID_COLOR")) #直線條及橫線條的線條顏色 techChartParam["CORD_INFO_COLOR"] = colorHex( techChartDict.get("CORD_INFO_COLOR")) #座標資訊的文字顏色 techChartParam["DATA_INFO_COLOR"] = colorHex( techChartDict.get("DATA_INFO_COLOR")) #資訊的文字顏色 techChartParam["CROSS_LINE_COLOR"] = colorHex( techChartDict.get("CROSS_LINE_COLOR")) #十字線顏色 self.tickGap = int(techChartDict.get("TICK_GAP")) #每筆資料間之間隔點數 self.shift_right = int(techChartDict.get("SHIFT_RIGHT")) #繪圖右邊位移距離 self.shift_bottom = int(techChartDict.get("SHIFT_BOTTOM")) #繪圖下方位移距離 self.shift_gap = int(techChartDict.get("SHIFT_GAP")) #兩圖形之間距 self.recordCount = int(techChartDict.get("RECORD_COUNT")) #下載筆數 self.priceFormulaId = int( techChartDict.get("PRICE_FORMULA_ID")) #價格MA公式代碼 self.next_id.disabled = True self.smaller_id.disabled = True self._klineDataTypeDropDown() self._technicalDropDown() refParam = {} for aKey in paramDict.keys(): refParam[aKey] = paramDict.get(aKey) for aKey in techChartParam.keys(): refParam[aKey] = techChartParam.get(aKey) refParam["Layout"] = self.body_layout #繪圖之layout refParam["Canvas"] = self.body_layout.canvas #繪圖之canvas refParam["TickWide"] = self.tickWide #一個tick的寬度(共有幾個點) refParam["TickGap"] = self.tickGap #tick與tick之間點數 self._calcDispNum() refParam["DispNum"] = self.dispNum #畫面顯示筆數 refParam["CurrentPage"] = self.currentPage #當前的頁次 refParam["InfoFunc"] = self._showInfo #顯示訊息之函式 refParam["IsDrawRect"] = True #是否畫外框 refParam["IsDrawXCordLine"] = True #是否顯示X軸直線 refParam["IsDrawXCordInfo"] = False #是否顯示X軸座標訊息 refParam["IsDrawYCordLine"] = True #是否顯示Y軸直線 refParam["IsDrawYCordInfo"] = True #是否顯示Y軸座標訊息 refParam["IsDrawCrossLine"] = True #是否顯示十字線 refParam["InstGroup"] = "KLine_chart" #InstructionGroup所使用之group值 refParam[ "FormatType"] = 1 #0.No format,1.float format,2.currency format refParam["DataType"] = self.klineDataType_index #資料類型 self.klineChart = SKLineChart(refParam) priceRefParam = {} for aKey in refParam.keys(): priceRefParam[aKey] = refParam.get(aKey) priceRefParam["IsPriceMA"] = True priceRefParam["InfoFunc"] = self._showPriceInfo #顯示訊息之函式 priceRefParam["IsDrawRect"] = False #是否畫外框 priceRefParam["IsDrawXCordLine"] = False #是否顯示X軸直線 priceRefParam["IsDrawXCordInfo"] = False #是否顯示X軸座標 priceRefParam["IsDrawYCordLine"] = False #是否顯示Y軸直線 priceRefParam["IsDrawYCordInfo"] = False #是否顯示Y軸座標 priceRefParam["IsDrawCrossLine"] = False #是否顯示十字線 priceRefParam["InstGroup"] = "PriceMaChart" lineSetup = self.formulaMapping.get(str(self.priceFormulaId))[0] priceRefParam["LineSetup"] = lineSetup self._createPriceInfoObj(self._getLineSetupList(lineSetup)) self.priceMixedChart = SMixedChart(priceRefParam) secRefParam = {} for aKey in refParam.keys(): secRefParam[aKey] = refParam.get(aKey) secRefParam["IsPriceMA"] = False secRefParam["InfoFunc"] = self._showMixedChartInfo #顯示訊息之函式 secRefParam["IsDrawRect"] = True #是否畫外框 secRefParam["IsDrawXCordLine"] = True #是否顯示X軸直線 secRefParam["IsDrawXCordInfo"] = True #是否顯示X軸座標訊息 secRefParam["IsDrawYCordLine"] = True #是否顯示Y軸直線 secRefParam["IsDrawYCordInfo"] = True #是否顯示Y軸座標訊息 secRefParam["IsDrawCrossLine"] = True #是否顯示十字線 secRefParam["InstGroup"] = "SecMixedChart" #InstructionGroup所使用之group值 lineSetup = self.formulaMapping.get(str(self.techType_index))[0] secRefParam["LineSetup"] = lineSetup self._createMixedChartInfoObj(self._getLineSetupList(lineSetup)) self.secMixedChart = SMixedChart(secRefParam) Clock.schedule_once(self.doQuoteStart, .5) #此段用意為讓畫面先顯示出來,再做後續的動作 self.bind(pos=self._charting) self.bind(size=self._charting) Window.bind(mouse_pos=self._mousePos)
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 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)
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 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)