def manageStrategy(page = ''): #1. check page is valid or not, if page not empty #2. if page = '' or not valid, list all strategy name #3. if page = valid strategy name, render strategy editor with preload strategy code #4. if page = 'newStrategy', render strategy editor with preload strategy template code strategyEditorForm = StrategyEditorForm() strategyManager = SimpleQuantStrategyManager() strategyNameList = strategyManager.getStrategyNameList() strategyHrefNameList = [StrategyHrefName(name) for name in strategyNameList] if strategyEditorForm.validate_on_submit(): print("submit strategy") newStrategyName = strategyEditorForm.strategyNameField.data if newStrategyName not in strategyNameList: newStrategyCode = strategyEditorForm.strategyEditorField.data strategyFilePath = os.path.join(os.path.dirname(__file__) + '/../strategy/' + newStrategyName + '.py') fo = open(strategyFilePath, 'w') fo.write(newStrategyCode) fo.close() return redirect('/manageStrategy') else: #TODO: prompt error when strategy name exist strategyEditorForm.strategyNameField.errors = 'Strategy Name has exist, please try another one!' return redirect('/manageStrategy/newStrategy') elif page == 'newStrategy': print("new Strategy") strategyHrefNameList.clear() return render_template('editor.html', title = 'StrategyEditor', strategyEditorForm = strategyEditorForm, strategyHrefNameList = strategyHrefNameList) elif page in strategyNameList: #render strategy editor with preload strategy code print("submit OK") strategyHrefNameList.clear() strategyEditorForm.strategyNameField.data = page strategyFilePath = os.path.join(os.path.dirname(__file__) + '/../strategy/' + page + '.py') fo = open(strategyFilePath, 'r') strategyEditorForm.strategyEditorField.data = fo.read() fo.close() return render_template('editor.html', title = 'StrategyEditor', strategyEditorForm = strategyEditorForm, strategyHrefNameList = strategyHrefNameList) else: #page = '' or not in strategy name or not valid #render as /manangeStrategy print("submit NOT OK") return render_template('editor.html', title = 'StrategyEditor', strategyEditorForm = strategyEditorForm, strategyHrefNameList = strategyHrefNameList)
def __init__(self, jsonString): self.name = jsonString['name'] self.strategyName = jsonString['strategyName'] self.object = jsonString['object'] self.duration = jsonString['duration'] self.id = jsonString['id'] self.objectData = pd.DataFrame() self.strategy = SimpleQuantStrategyManager().getStrategyInstance( self.strategyName)() self.loopIndex = 0 self.cashHistory = [] self.positionHistory = [] self.marketValue = []
def __init__(self, stockSymbol, strategyName, startDate, endDate, feedbackQueue): SimpleQuantSafeProcess.__init__(self, feedbackQueue) self.strategy_manager = SimpleQuantStrategyManager() self.data_manager = SimpleQuantUIDataManager(stockSymbol, startDate, endDate) #TODO:fix crash cause by event engine #self.event_engine = SimpleQuantEventEngine() self.strategy_name = strategyName
def transition(): transitionPanelForm = TransitionPanelForm() stockSymbol = session.get('stockSymbol') strategyManager = SimpleQuantStrategyManager() transitionPanelForm.strategyListField.choices = [(name, name) for name in strategyManager.getStrategyNameList()] if transitionPanelForm.validate_on_submit(): #TODO: run strategy in new process #1. start transition in new process #2. display page as well. wait until transition finish. It's no need render template instantly after strat transtion, # because javascript can display page as well when click 'start strategy', while in backend, parent process wait for # transition process finish, then render the template again, the well will disapear. #3. render the template strategyName = transitionPanelForm.strategyListField.data startDate = transitionPanelForm.startDateField.data endDate = transitionPanelForm.endDateField.data transition = SimpleQuantTransition(stockSymbol, strategyName, startDate, endDate, feedback_queue) transition.start() #wait transition finish transition.join() return render_template("transition.html", title = 'Trasition', transitionPanelForm = transitionPanelForm) else: endDate = datetime.datetime.today() deltaDays = datetime.timedelta(days=-60) startDate = endDate + deltaDays dataManager = SimpleQuantUIDataManager(stockSymbol, startDate, endDate) hqData = dataManager.getStockData() with open('app/static/json/hqData.json', 'w') as f: f.write(json.dumps(hqData)) return render_template("transition.html", title = 'Trasition', transitionPanelForm = transitionPanelForm)
class SimpleQuantTransition(SimpleQuantSafeProcess): def __init__(self, stockSymbol, strategyName, startDate, endDate, feedbackQueue): SimpleQuantSafeProcess.__init__(self, feedbackQueue) self.strategy_manager = SimpleQuantStrategyManager() self.data_manager = SimpleQuantUIDataManager(stockSymbol, startDate, endDate) #TODO:fix crash cause by event engine #self.event_engine = SimpleQuantEventEngine() self.strategy_name = strategyName def getStockData(self): hqData = self.data_manager.getStockData() return hqData #TODO: remove runStrategy() when multi-process done def runStrategy(self, strategyName): MyLogger.info("Run Strategy") self.strategy_manager.setStrategyName(strategyName) self.stock_strategy = self.strategy_manager.getStrategyInstance()(self.data_manager) self.profitsData = self.stock_strategy.backTest() return self.profitsData def updateTransitionContext(self, startDate, endDate): self.data_manager.setStockContext(startDate, endDate) def getStrategyNameList(self): return self.strategy_manager.getStrategyNameList() def saferun(self): MyLogger.info("Start Transition") MyLogger.info("Run Strategy") self.strategy_manager.setStrategyName(self.strategy_name) self.stock_strategy = self.strategy_manager.getStrategyInstance()(self.data_manager) self.profitsData = self.stock_strategy.backTest() self.endUp() def endUp(self): MyLogger.info("End Up Transition") hqData = self.getStockData() profits = self.profitsData with open('app/static/json/hqData.json', 'w') as f: f.write(json.dumps(hqData)) with open('app/static/json/profits.json', 'w') as f: f.write(json.dumps(profits))
class SimpleQuantTransition: def __init__(self, jsonString): self.name = jsonString['name'] self.strategyName = jsonString['strategyName'] self.object = jsonString['object'] self.duration = jsonString['duration'] self.id = jsonString['id'] self.objectData = pd.DataFrame() self.strategy = SimpleQuantStrategyManager().getStrategyInstance( self.strategyName)() self.loopIndex = 0 self.cashHistory = [] self.positionHistory = [] self.marketValue = [] def __call__(self): # use transition id as topic logger = SimpleQuantLogger(self.name, '127.0.0.1:4321') logger.info('{name} is running {strategyName}'.format( name=self.name, strategyName=self.strategyName)) self.runStrategy() evaluator = SimpleQuantEvaluator() evaluator.performEvaluate(self) report = evaluator.getReport() logger.info('{name} is running {strategyName}....Done'.format( name=self.name, strategyName=self.strategyName)) return self.objectData.to_json(), json.dumps(report) def getTransitionName(self): return self.name def getTransitionStrategyName(self): return self.strategyName def getTransitionObject(self): return self.object def getTransitionDuration(self): return self.duration def setTransitionObjectData(self, objectData): self.objectData = objectData def runStrategy(self): self.initial() decisionList = [] for currentData in self.objectData.itertuples(name='FeedData'): decision = self.strategy.loop(currentData, decisionList) self.performDecision(decision) decisionList.append(decision) self.loopIndex += 1 self.end() def initial(self): self.strategy.tearUp() self.cashHistory.append(100000) self.positionHistory.append(0) def performDecision(self, decision): # use next open price as deal price price = self.getDealPrice() # no available price if price == 0: decision.volumn = 0 currentCash = self.cashHistory[self.loopIndex] currentPosition = self.positionHistory[self.loopIndex] # market value depends on current cash and current object value # current cash and current position was calcualted in previous loop # for example, in day n, if decision was made for bid/ask, # the cash and position wouldn't change till day n+1, because the decision was made by # today's close price, that's means transaction can't happend till next day. marketValue = currentCash + currentPosition * self.objectData.loc[ self.loopIndex, 'close'] if decision.action == BID: requiredCash = price * decision.volumn if requiredCash < currentCash: currentCash -= requiredCash currentPosition += decision.volumn elif decision.action == ASK: if currentPosition - decision.volumn >= 0: gainCash = price * decision.volumn currentCash += gainCash if price != 0: self.cashHistory.append(currentCash) self.positionHistory.append(currentPosition) self.marketValue.append(marketValue) def getDealPrice(self): priceIndex = self.loopIndex + 1 if priceIndex >= self.objectData.shape[0]: return 0 else: return self.objectData.loc[priceIndex, 'open'] def end(self): self.strategy.tearDown() self.objectData = self.objectData.assign(marketValue=self.marketValue)
def __init__(self, stockSymbol): QtGui.QDialog.__init__(self) #today is endDate, startDate is earlier than endDate endDate = datetime.datetime.today() deltaDays = datetime.timedelta(days=-60) startDate = endDate + deltaDays self.strategy_manager = SimpleQuantStrategyManager() self.data_manager = SimpleQuantUIDataManager(stockSymbol, startDate, endDate) self.event_engine = SimpleQuantEventEngine() #self.stock_strategy = SimpleQuantStrategyMACD(self.data_manager) self.setGeometry(100, 100, 850, 650) self.main_widget = QtGui.QWidget(self) self.start_date = QtGui.QDateEdit(self) self.start_date.setCalendarPopup(True) startDateStr = startDate.strftime("%Y-%m-%d") self.start_date.setDate(QDate.fromString(startDateStr, 'yyyy-MM-dd')) startDateLabel = QtGui.QLabel('StartDate: ', self) endDateStr = endDate.strftime("%Y-%m-%d") self.end_date = QtGui.QDateEdit(self) self.end_date.setCalendarPopup(True) self.end_date.setDate(QDate.fromString(endDateStr, 'yyyy-MM-dd')) endDateLabel = QtGui.QLabel('EndDate: ', self) self.update_button = QtGui.QPushButton("Update") self.update_button.clicked.connect(self.updateButtonClicked) self.transition_layout = QtGui.QVBoxLayout(self.main_widget) self.stock_layout = QtGui.QHBoxLayout() self.stock_widget_layout = QtGui.QVBoxLayout() self.stock_widget_layout.addWidget(startDateLabel) self.stock_widget_layout.addWidget(self.start_date) self.stock_widget_layout.addWidget(endDateLabel) self.stock_widget_layout.addWidget(self.end_date) hqData = self.data_manager.getStockData() self.stock_canvas = SimpleQuantUIStrategyMplCanvas(hqData) self.stock_layout.addStretch(1) self.stock_layout.addWidget(self.stock_canvas) self.stock_layout.addLayout(self.stock_widget_layout) self.stock_layout.addWidget(self.update_button) self.strategy_layout = QtGui.QHBoxLayout() self.strategy_button = QtGui.QPushButton("Run") self.strategy_button.clicked.connect(self.strategyButtonClicked) self.strategy_combobox = QtGui.QComboBox() self.strategy_combobox.activated[str].connect(self.strategyChanged) [self.strategy_combobox.addItem(strategyName) for strategyName in self.strategy_manager.getStrategyNameList()] for entry in hqData: entry[1] = '0' self.strategy_canvas = SimpleQuantUIStrategyMplCanvas(hqData) self.strategy_layout.addStretch(1) self.strategy_layout.addWidget(self.strategy_canvas) self.strategy_layout.addWidget(self.strategy_button) self.strategy_layout.addWidget(self.strategy_combobox) self.online_radio_button = QtGui.QRadioButton('Online') self.offline_radio_button = QtGui.QRadioButton('Offline') self.online_radio_button.toggled.connect(self.onlineClicked) self.offline_radio_button.toggled.connect(self.offlineClicked) self.transition_layout.addLayout(self.stock_layout) self.transition_layout.addLayout(self.strategy_layout) self.transition_layout.addWidget(self.online_radio_button) self.transition_layout.addWidget(self.offline_radio_button)
class SimpleQuantUITransitionDialog(QtGui.QDialog): def __init__(self, stockSymbol): QtGui.QDialog.__init__(self) #today is endDate, startDate is earlier than endDate endDate = datetime.datetime.today() deltaDays = datetime.timedelta(days=-60) startDate = endDate + deltaDays self.strategy_manager = SimpleQuantStrategyManager() self.data_manager = SimpleQuantUIDataManager(stockSymbol, startDate, endDate) self.event_engine = SimpleQuantEventEngine() #self.stock_strategy = SimpleQuantStrategyMACD(self.data_manager) self.setGeometry(100, 100, 850, 650) self.main_widget = QtGui.QWidget(self) self.start_date = QtGui.QDateEdit(self) self.start_date.setCalendarPopup(True) startDateStr = startDate.strftime("%Y-%m-%d") self.start_date.setDate(QDate.fromString(startDateStr, 'yyyy-MM-dd')) startDateLabel = QtGui.QLabel('StartDate: ', self) endDateStr = endDate.strftime("%Y-%m-%d") self.end_date = QtGui.QDateEdit(self) self.end_date.setCalendarPopup(True) self.end_date.setDate(QDate.fromString(endDateStr, 'yyyy-MM-dd')) endDateLabel = QtGui.QLabel('EndDate: ', self) self.update_button = QtGui.QPushButton("Update") self.update_button.clicked.connect(self.updateButtonClicked) self.transition_layout = QtGui.QVBoxLayout(self.main_widget) self.stock_layout = QtGui.QHBoxLayout() self.stock_widget_layout = QtGui.QVBoxLayout() self.stock_widget_layout.addWidget(startDateLabel) self.stock_widget_layout.addWidget(self.start_date) self.stock_widget_layout.addWidget(endDateLabel) self.stock_widget_layout.addWidget(self.end_date) hqData = self.data_manager.getStockData() self.stock_canvas = SimpleQuantUIStrategyMplCanvas(hqData) self.stock_layout.addStretch(1) self.stock_layout.addWidget(self.stock_canvas) self.stock_layout.addLayout(self.stock_widget_layout) self.stock_layout.addWidget(self.update_button) self.strategy_layout = QtGui.QHBoxLayout() self.strategy_button = QtGui.QPushButton("Run") self.strategy_button.clicked.connect(self.strategyButtonClicked) self.strategy_combobox = QtGui.QComboBox() self.strategy_combobox.activated[str].connect(self.strategyChanged) [self.strategy_combobox.addItem(strategyName) for strategyName in self.strategy_manager.getStrategyNameList()] for entry in hqData: entry[1] = '0' self.strategy_canvas = SimpleQuantUIStrategyMplCanvas(hqData) self.strategy_layout.addStretch(1) self.strategy_layout.addWidget(self.strategy_canvas) self.strategy_layout.addWidget(self.strategy_button) self.strategy_layout.addWidget(self.strategy_combobox) self.online_radio_button = QtGui.QRadioButton('Online') self.offline_radio_button = QtGui.QRadioButton('Offline') self.online_radio_button.toggled.connect(self.onlineClicked) self.offline_radio_button.toggled.connect(self.offlineClicked) self.transition_layout.addLayout(self.stock_layout) self.transition_layout.addLayout(self.strategy_layout) self.transition_layout.addWidget(self.online_radio_button) self.transition_layout.addWidget(self.offline_radio_button) def updateButtonClicked(self): endDate = self.end_date.date().toPyDateTime() startDate = self.start_date.date().toPyDateTime() self.data_manager.setStockContext(startDate, endDate) stockData = self.data_manager.getStockData() self.stock_canvas.updateFigure(stockData) self.stock_canvas.draw() def strategyButtonClicked(self): self.stock_strategy = self.strategy_manager.getStrategyInstance()(self.data_manager) profitsData = self.stock_strategy.backTest() self.strategy_canvas.updateFigure(profitsData) self.strategy_canvas.draw() MyLogger.info("Done!") def strategyChanged(self, strategyName): self.strategy_manager.setStrategyName(strategyName) def onlineClicked(self): self.event_engine.start() self.event_engine.register(EVENT_TIMER, self.timerHandler) def offlineClicked(self): self.event_engine.unregister(EVENT_TIMER, self.timerHandler) self.event_engine.stop() def timerHandler(self, event): self.data_manager.retreiveRealTimeQuotes()