Example #1
0
    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()
Example #3
0
 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
Example #4
0
    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()
Example #5
0
 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)
Example #6
0
    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)
Example #7
0
 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)
Example #8
0
    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)
Example #9
0
    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)
Example #10
0
    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]"
Example #11
0
    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)
Example #12
0
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()
Example #13
0
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
Example #14
0
    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)
Example #15
0
    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)
Example #16
0
 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"))
Example #17
0
    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)
Example #18
0
 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)
Example #19
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)
Example #20
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()
Example #21
0
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)