From 271f19de6611084f718c64eea7efaa603b7d8061 Mon Sep 17 00:00:00 2001 From: Denis Tereshkin Date: Tue, 11 Dec 2018 06:37:50 +0700 Subject: [PATCH] Strategy execution --- .gitignore | 2 + src/nailab/data/csvfolderdatasource.py | 2 +- src/nailab/data/datasourcemanager.py | 2 +- src/nailab/execution/executor.py | 8 +- src/nailab/nailab.py | 2 + src/nailab/templates/new_strategy.py | 1 + src/nailab/ui/__init__.py | 0 src/nailab/ui/mainwindow.py | 51 +++++--- src/nailab/ui/strategywidget.py | 134 +++++++++++++++++++- src/nailab/ui_gen/mainwindow.py | 14 +- src/nailab/ui_gen/strategywidget.py | 72 +++++++++-- ui/mainwindow.ui | 41 +++++- ui/strategywidget.ui | 169 +++++++++++++++++++------ 13 files changed, 421 insertions(+), 77 deletions(-) mode change 100644 => 100755 src/nailab/nailab.py create mode 100644 src/nailab/ui/__init__.py diff --git a/.gitignore b/.gitignore index bf6279b..55530b8 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ build/* *.pyc src/*.egg-info/* *~ +\#* +\#*.* diff --git a/src/nailab/data/csvfolderdatasource.py b/src/nailab/data/csvfolderdatasource.py index ceab137..d458eb8 100644 --- a/src/nailab/data/csvfolderdatasource.py +++ b/src/nailab/data/csvfolderdatasource.py @@ -1,5 +1,5 @@ -from nailab.data.datasource import DataSource +from data.datasource import DataSource from naiback.data.feeds.genericcsvfeed import GenericCSVFeed diff --git a/src/nailab/data/datasourcemanager.py b/src/nailab/data/datasourcemanager.py index 6094e76..8e26855 100644 --- a/src/nailab/data/datasourcemanager.py +++ b/src/nailab/data/datasourcemanager.py @@ -1,5 +1,5 @@ -from nailab.data.csvfolderdatasource import CsvFolderDataSource +from data.csvfolderdatasource import CsvFolderDataSource class DataSourceManager: diff --git a/src/nailab/execution/executor.py b/src/nailab/execution/executor.py index a546041..de9c80f 100644 --- a/src/nailab/execution/executor.py +++ b/src/nailab/execution/executor.py @@ -9,7 +9,7 @@ class Executor: def __init__(self): pass - def execute_from_file(self, path, feeds): + def execute_from_file(self, path, feeds, extents=None): loader = SourceFileLoader('execution._current_strategy', path) mod = loader.load_module() for item in inspect.getmembers(mod, inspect.isclass): @@ -18,7 +18,11 @@ class Executor: strategy = klass() for feed in feeds: strategy.add_feed(feed) - strategy.run() + + if extents is None: + strategy.run() + else: + strategy.run(from_time=extents[0], to_time=extents[1]) results = strategy.get_analyzer('stats').get_result() trades = strategy.get_analyzer('tradeslist').get_result() diff --git a/src/nailab/nailab.py b/src/nailab/nailab.py old mode 100644 new mode 100755 index af7b04a..856952d --- a/src/nailab/nailab.py +++ b/src/nailab/nailab.py @@ -1,7 +1,9 @@ +#!/usr/bin/env python3 import sys from PyQt5.QtWidgets import QApplication from PyQt5 import QtCore + from ui.mainwindow import MainWindow def main(): diff --git a/src/nailab/templates/new_strategy.py b/src/nailab/templates/new_strategy.py index 82571ea..711c35f 100644 --- a/src/nailab/templates/new_strategy.py +++ b/src/nailab/templates/new_strategy.py @@ -1,6 +1,7 @@ new_strategy_template = ''' from naiback.strategy import Strategy +from naiback.indicators import * class MyStrategy(Strategy): diff --git a/src/nailab/ui/__init__.py b/src/nailab/ui/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/nailab/ui/mainwindow.py b/src/nailab/ui/mainwindow.py index 255d419..ee2b6f3 100644 --- a/src/nailab/ui/mainwindow.py +++ b/src/nailab/ui/mainwindow.py @@ -5,7 +5,7 @@ import importlib.util import inspect from execution.executor import Executor -from naiback.data.feeds.genericcsvfeed import GenericCSVFeed +from data.datasourcemanager import DataSourceManager from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.Qsci import * @@ -14,9 +14,7 @@ from ui_gen.mainwindow import Ui_MainWindow from ui.strategywidget import StrategyWidget from naiback.strategy import Strategy - -def is_strategy(obj): - return inspect.isclass(obj) and Strategy in inspect.getmro(obj)[1:] +from templates.new_strategy import new_strategy_template class MainWindow(QtWidgets.QMainWindow): @@ -24,6 +22,8 @@ class MainWindow(QtWidgets.QMainWindow): super().__init__(parent) self.sources = [] + self.datasourcemanager = DataSourceManager() + self.datasourcemanager.load_sources() self.ui = Ui_MainWindow() self.ui.setupUi(self) @@ -32,7 +32,7 @@ class MainWindow(QtWidgets.QMainWindow): pass def newStrategy(self): - self._makeEditor() + self._makeEditor(content=new_strategy_template) def openStrategy(self): settings = QtCore.QSettings() @@ -42,24 +42,43 @@ class MainWindow(QtWidgets.QMainWindow): self._makeEditor(filename, os.path.basename(filename), f.read()) settings.setValue("open_strategy_path", os.path.dirname(filename)) + def saveStrategy(self): + settings = QtCore.QSettings() + currentWidget = self.ui.tabs.currentWidget() + if currentWidget.source_file is None: + currentWidget.source_file = QtWidgets.QFileDialog.getSaveFileName(self, self.tr("Select a file..."), settings.value("save_strategy_path"), self.tr("Python (*.py);;All (*.*, *)"))[0] + if currentWidget.source_file != "": + settings.setValue("save_strategy_path", os.path.dirname(currentWidget.source_file)) + self.ui.tabs.setTabText(self.ui.tabs.currentIndex(), os.path.basename(currentWidget.source_file)) + if currentWidget.source_file != "": + currentWidget.save() + def executeStrategy(self): - source_file = self.sources[self.ui.tabs.currentIndex()] + source_file = self.ui.tabs.currentWidget().source_file executor = Executor() - result = executor.execute_from_file(source_file, []) - print(result) - -# spec = importlib.util.spec_from_file_location("m", source_file) -# mod = importlib.util.module_from_spec(spec) -# spec.loader.exec_module(mod) -# classes = inspect.getmembers(mod, is_strategy) -# strategy_class = classes[0][0] - + selected_feed_ids = self.ui.tabs.currentWidget().get_selected_feeds() + selected_feeds = [] + for (source_id, feed_id) in selected_feed_ids: + try: + selected_feeds.append(self.datasourcemanager.get_source(source_id).get_feed(feed_id)) + except e: + print('Error: ' + str(e)) + + try: + result = executor.execute_from_file(source_file, selected_feeds, self.ui.tabs.currentWidget().get_time_window()) + print(result) + self.ui.tabs.currentWidget().set_result(result) + except Exception as e: + print(e) + def tabCloseRequested(self, tab_index): del self.sources[tab_index] + self.ui.tabs.widget(tab_index).save_state() self.ui.tabs.removeTab(tab_index) def _makeEditor(self, source_file=None, tab_name="Untitled", content=None): - editor = StrategyWidget(self, content) + editor = StrategyWidget(self.datasourcemanager, source_file, self, content) self.sources.append(source_file) self.ui.tabs.addTab(editor, tab_name) + diff --git a/src/nailab/ui/strategywidget.py b/src/nailab/ui/strategywidget.py index dcfacde..97b7b95 100644 --- a/src/nailab/ui/strategywidget.py +++ b/src/nailab/ui/strategywidget.py @@ -4,14 +4,21 @@ from PyQt5.Qsci import * from ui_gen.strategywidget import Ui_StrategyWidget +ROLE_FEED_ID = QtCore.Qt.UserRole + 1 + class StrategyWidget(QtWidgets.QWidget): - def __init__(self, parent=None, content=None): + def __init__(self, datasourcemanager, source_file, parent=None, content=None): super().__init__(parent) self.ui = Ui_StrategyWidget() self.ui.setupUi(self) + self.source_file = source_file + + self.datasourcemanager = datasourcemanager + self.update_feeds_list() + self.ui.splitter.setSizes([20, 80]) self.ui.splitter.setStretchFactor(0, 1) self.ui.splitter.setStretchFactor(1, 1) @@ -26,3 +33,128 @@ class StrategyWidget(QtWidgets.QWidget): lexer.setFont(font) self.ui.editor.setLexer(lexer) self.ui.editor.setUtf8(True) + + self.result = [] + self.result_widget = None + + s = QtCore.QSettings() + if s.value("time_window") is not None: + (from_time, to_time) = s.value("time_window") + self.ui.rb_timeWindow.setChecked(True) + self.ui.dte_from.setDateTime(from_time) + self.ui.dte_to.setDateTime(to_time) + + def save_state(self): + s = QtCore.QSettings() + if self.ui.rb_allData.isChecked(): + s.setValue("time_window", None) + else: + s.setValue("time_window", (self.ui.dte_from.dateTime(), self.ui.dte_to.dateTime())) + + def save(self): + with open(self.source_file, "w") as f: + f.write(self.ui.editor.text()) + + def get_time_window(self): + if self.ui.rb_allData.isChecked(): + return None + elif self.ui.rb_timeWindow.isChecked(): + return (self.ui.dte_from.dateTime(), self.ui.dte_to.dateTime()) + + def update_feeds_list(self): + sources = self.datasourcemanager.all_sources() + for source in sources: + src_item = QtWidgets.QTreeWidgetItem(self.ui.tw_feeds) + src_item.setText(0, source.name) + src_item.setData(0, ROLE_FEED_ID, "") + for feed in source.available_feeds(): + feed_item = QtWidgets.QTreeWidgetItem(src_item) + feed_item.setText(0, feed) + feed_item.setData(0, ROLE_FEED_ID, (source.name, feed)) + + def get_selected_feeds(self): + feeds = [] + items = self.ui.tw_feeds.selectedItems() + for item in items: + feeds.append(item.data(0, ROLE_FEED_ID)) + return feeds + + def set_result(self, result): + self.result = result + self.update_result() + + + def update_result(self): + if self.result_widget is None: + self.result_widget = QtWidgets.QTreeWidget(self) + self.ui.tabs.addTab(self.result_widget, "Result") + + rw = self.result_widget + rw.clear() + + rw.setHeaderLabels(["", "Long", "Short", "All"]) + total_trades = QtWidgets.QTreeWidgetItem(self.result_widget) + total_trades.setText(0, "Total trades") + total_trades.setText(1, "{:d}".format(self.result[0]['long']['number_of_trades'])) + total_trades.setText(2, "{:d}".format(self.result[0]['short']['number_of_trades'])) + total_trades.setText(3, "{:d}".format(self.result[0]['all']['number_of_trades'])) + + won_trades = QtWidgets.QTreeWidgetItem(self.result_widget) + won_trades.setText(0, "Won trades") + won_trades.setText(1, "{:d}".format(self.result[0]['long']['won'])) + won_trades.setText(2, "{:d}".format(self.result[0]['short']['won'])) + won_trades.setText(3, "{:d}".format(self.result[0]['all']['won'])) + + lost_trades = QtWidgets.QTreeWidgetItem(self.result_widget) + lost_trades.setText(0, "Lost trades") + lost_trades.setText(1, "{:d}".format(self.result[0]['long']['lost'])) + lost_trades.setText(2, "{:d}".format(self.result[0]['short']['lost'])) + lost_trades.setText(3, "{:d}".format(self.result[0]['all']['lost'])) + + net_profit = QtWidgets.QTreeWidgetItem(self.result_widget) + net_profit.setText(0, "Net profit") + net_profit.setText(1, "{:.3f}".format(self.result[0]['long']['net_profit'])) + net_profit.setText(2, "{:.3f}".format(self.result[0]['short']['net_profit'])) + net_profit.setText(3, "{:.3f}".format(self.result[0]['all']['net_profit'])) + + total_won = QtWidgets.QTreeWidgetItem(self.result_widget) + total_won.setText(0, "Total won") + total_won.setText(1, "{:.3f}".format(self.result[0]['long']['total_won'])) + total_won.setText(2, "{:.3f}".format(self.result[0]['short']['total_won'])) + total_won.setText(3, "{:.3f}".format(self.result[0]['all']['total_won'])) + + total_lost = QtWidgets.QTreeWidgetItem(self.result_widget) + total_lost.setText(0, "Total lost") + total_lost.setText(1, "{:.3f}".format(self.result[0]['long']['total_lost'])) + total_lost.setText(2, "{:.3f}".format(self.result[0]['short']['total_lost'])) + total_lost.setText(3, "{:.3f}".format(self.result[0]['all']['total_lost'])) + + average_pnl = QtWidgets.QTreeWidgetItem(self.result_widget) + average_pnl.setText(0, "Average pnl") + average_pnl.setText(1, "{:.3f}".format(self.result[0]['long']['avg'])) + average_pnl.setText(2, "{:.3f}".format(self.result[0]['short']['avg'])) + average_pnl.setText(3, "{:.3f}".format(self.result[0]['all']['avg'])) + + average_percentage = QtWidgets.QTreeWidgetItem(self.result_widget) + average_percentage.setText(0, "Average %") + average_percentage.setText(1, "{:.3f}".format(self.result[0]['long']['avg_percentage'])) + average_percentage.setText(2, "{:.3f}".format(self.result[0]['short']['avg_percentage'])) + average_percentage.setText(3, "{:.3f}".format(self.result[0]['all']['avg_percentage'])) + + average_bars_in_trade = QtWidgets.QTreeWidgetItem(self.result_widget) + average_bars_in_trade.setText(0, "Average bars in trade") + average_bars_in_trade.setText(1, "{:.3f}".format(self.result[0]['long']['avg_bars'])) + average_bars_in_trade.setText(2, "{:.3f}".format(self.result[0]['short']['avg_bars'])) + average_bars_in_trade.setText(3, "{:.3f}".format(self.result[0]['all']['avg_bars'])) + + profit_factor = QtWidgets.QTreeWidgetItem(self.result_widget) + profit_factor.setText(0, "Profit factor") + profit_factor.setText(1, "{:.3f}".format(self.result[0]['long']['profit_factor'])) + profit_factor.setText(2, "{:.3f}".format(self.result[0]['short']['profit_factor'])) + profit_factor.setText(3, "{:.3f}".format(self.result[0]['all']['profit_factor'])) + + self.result_widget.resizeColumnToContents(0) + + + + diff --git a/src/nailab/ui_gen/mainwindow.py b/src/nailab/ui_gen/mainwindow.py index 796dae5..6f99a6d 100644 --- a/src/nailab/ui_gen/mainwindow.py +++ b/src/nailab/ui_gen/mainwindow.py @@ -11,7 +11,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") - MainWindow.resize(1050, 712) + MainWindow.resize(1060, 587) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.gridLayout = QtWidgets.QGridLayout(self.centralwidget) @@ -23,7 +23,7 @@ class Ui_MainWindow(object): self.gridLayout.addWidget(self.tabs, 0, 0, 1, 1) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) - self.menubar.setGeometry(QtCore.QRect(0, 0, 1050, 23)) + self.menubar.setGeometry(QtCore.QRect(0, 0, 1060, 23)) self.menubar.setObjectName("menubar") self.menuFile = QtWidgets.QMenu(self.menubar) self.menuFile.setObjectName("menuFile") @@ -33,6 +33,9 @@ class Ui_MainWindow(object): self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) + self.toolBar = QtWidgets.QToolBar(MainWindow) + self.toolBar.setObjectName("toolBar") + MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar) self.actionOpenTrades = QtWidgets.QAction(MainWindow) self.actionOpenTrades.setObjectName("actionOpenTrades") self.actionNew_strategy = QtWidgets.QAction(MainWindow) @@ -41,11 +44,15 @@ class Ui_MainWindow(object): self.actionOpen_strategy.setObjectName("actionOpen_strategy") self.actionExecute = QtWidgets.QAction(MainWindow) self.actionExecute.setObjectName("actionExecute") + self.actionSave_strategy = QtWidgets.QAction(MainWindow) + self.actionSave_strategy.setObjectName("actionSave_strategy") self.menuFile.addAction(self.actionNew_strategy) self.menuFile.addAction(self.actionOpen_strategy) self.menuBacktest.addAction(self.actionExecute) self.menubar.addAction(self.menuFile.menuAction()) self.menubar.addAction(self.menuBacktest.menuAction()) + self.toolBar.addAction(self.actionSave_strategy) + self.toolBar.addAction(self.actionExecute) self.retranslateUi(MainWindow) self.tabs.setCurrentIndex(-1) @@ -53,6 +60,7 @@ class Ui_MainWindow(object): self.tabs.tabCloseRequested['int'].connect(MainWindow.tabCloseRequested) self.actionNew_strategy.triggered.connect(MainWindow.newStrategy) self.actionExecute.triggered.connect(MainWindow.executeStrategy) + self.actionSave_strategy.triggered.connect(MainWindow.saveStrategy) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): @@ -60,8 +68,10 @@ class Ui_MainWindow(object): MainWindow.setWindowTitle(_translate("MainWindow", "Nailab")) self.menuFile.setTitle(_translate("MainWindow", "File")) self.menuBacktest.setTitle(_translate("MainWindow", "Backtest")) + self.toolBar.setWindowTitle(_translate("MainWindow", "toolBar")) self.actionOpenTrades.setText(_translate("MainWindow", "Open...")) self.actionNew_strategy.setText(_translate("MainWindow", "New strategy")) self.actionOpen_strategy.setText(_translate("MainWindow", "Open strategy")) self.actionExecute.setText(_translate("MainWindow", "Execute")) + self.actionSave_strategy.setText(_translate("MainWindow", "Save strategy")) diff --git a/src/nailab/ui_gen/strategywidget.py b/src/nailab/ui_gen/strategywidget.py index 7f50101..2827d40 100644 --- a/src/nailab/ui_gen/strategywidget.py +++ b/src/nailab/ui_gen/strategywidget.py @@ -11,25 +11,59 @@ from PyQt5 import QtCore, QtGui, QtWidgets class Ui_StrategyWidget(object): def setupUi(self, StrategyWidget): StrategyWidget.setObjectName("StrategyWidget") - StrategyWidget.resize(839, 464) - self.gridLayout = QtWidgets.QGridLayout(StrategyWidget) + StrategyWidget.resize(977, 569) + self.gridLayout_3 = QtWidgets.QGridLayout(StrategyWidget) + self.gridLayout_3.setContentsMargins(1, 1, 1, 1) + self.gridLayout_3.setObjectName("gridLayout_3") + self.tabs = QtWidgets.QTabWidget(StrategyWidget) + self.tabs.setObjectName("tabs") + self.tab = QtWidgets.QWidget() + self.tab.setObjectName("tab") + self.gridLayout = QtWidgets.QGridLayout(self.tab) + self.gridLayout.setContentsMargins(1, 1, 1, 1) self.gridLayout.setObjectName("gridLayout") - self.splitter = QtWidgets.QSplitter(StrategyWidget) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.splitter.sizePolicy().hasHeightForWidth()) - self.splitter.setSizePolicy(sizePolicy) + self.splitter = QtWidgets.QSplitter(self.tab) self.splitter.setOrientation(QtCore.Qt.Horizontal) self.splitter.setObjectName("splitter") - self.treeWidget = QtWidgets.QTreeWidget(self.splitter) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Expanding) + self.gridLayoutWidget = QtWidgets.QWidget(self.splitter) + self.gridLayoutWidget.setObjectName("gridLayoutWidget") + self.gridLayout_2 = QtWidgets.QGridLayout(self.gridLayoutWidget) + self.gridLayout_2.setObjectName("gridLayout_2") + self.dte_to = QtWidgets.QDateTimeEdit(self.gridLayoutWidget) + self.dte_to.setObjectName("dte_to") + self.gridLayout_2.addWidget(self.dte_to, 3, 1, 1, 1) + self.dte_from = QtWidgets.QDateTimeEdit(self.gridLayoutWidget) + self.dte_from.setObjectName("dte_from") + self.gridLayout_2.addWidget(self.dte_from, 2, 1, 1, 1) + self.label_2 = QtWidgets.QLabel(self.gridLayoutWidget) + self.label_2.setObjectName("label_2") + self.gridLayout_2.addWidget(self.label_2, 3, 0, 1, 1) + self.rb_allData = QtWidgets.QRadioButton(self.gridLayoutWidget) + self.rb_allData.setChecked(True) + self.rb_allData.setObjectName("rb_allData") + self.gridLayout_2.addWidget(self.rb_allData, 0, 0, 1, 2) + self.tw_feeds = QtWidgets.QTreeWidget(self.gridLayoutWidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.tw_feeds.sizePolicy().hasHeightForWidth()) + self.tw_feeds.setSizePolicy(sizePolicy) + self.tw_feeds.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection) + self.tw_feeds.setHeaderHidden(True) + self.tw_feeds.setObjectName("tw_feeds") + self.tw_feeds.headerItem().setText(0, "1") + self.gridLayout_2.addWidget(self.tw_feeds, 4, 0, 1, 2) + self.label = QtWidgets.QLabel(self.gridLayoutWidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.treeWidget.sizePolicy().hasHeightForWidth()) - self.treeWidget.setSizePolicy(sizePolicy) - self.treeWidget.setObjectName("treeWidget") - self.treeWidget.headerItem().setText(0, "1") + sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth()) + self.label.setSizePolicy(sizePolicy) + self.label.setObjectName("label") + self.gridLayout_2.addWidget(self.label, 2, 0, 1, 1) + self.rb_timeWindow = QtWidgets.QRadioButton(self.gridLayoutWidget) + self.rb_timeWindow.setObjectName("rb_timeWindow") + self.gridLayout_2.addWidget(self.rb_timeWindow, 1, 0, 1, 2) self.editor = Qsci.QsciScintilla(self.splitter) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) @@ -39,12 +73,22 @@ class Ui_StrategyWidget(object): self.editor.setMinimumSize(QtCore.QSize(300, 0)) self.editor.setObjectName("editor") self.gridLayout.addWidget(self.splitter, 0, 0, 1, 1) + self.tabs.addTab(self.tab, "") + self.gridLayout_3.addWidget(self.tabs, 0, 0, 1, 1) self.retranslateUi(StrategyWidget) + self.tabs.setCurrentIndex(0) QtCore.QMetaObject.connectSlotsByName(StrategyWidget) def retranslateUi(self, StrategyWidget): _translate = QtCore.QCoreApplication.translate StrategyWidget.setWindowTitle(_translate("StrategyWidget", "Form")) + self.dte_to.setDisplayFormat(_translate("StrategyWidget", "dd.MM.yyyy H:mm")) + self.dte_from.setDisplayFormat(_translate("StrategyWidget", "dd.MM.yyyy H:mm")) + self.label_2.setText(_translate("StrategyWidget", "To")) + self.rb_allData.setText(_translate("StrategyWidget", "All data")) + self.label.setText(_translate("StrategyWidget", "From")) + self.rb_timeWindow.setText(_translate("StrategyWidget", "Time window")) + self.tabs.setTabText(self.tabs.indexOf(self.tab), _translate("StrategyWidget", "Code")) from PyQt5 import Qsci diff --git a/ui/mainwindow.ui b/ui/mainwindow.ui index 8a95fc9..992b9c5 100644 --- a/ui/mainwindow.ui +++ b/ui/mainwindow.ui @@ -6,8 +6,8 @@ 0 0 - 1050 - 712 + 1060 + 587 @@ -44,7 +44,7 @@ 0 0 - 1050 + 1060 23 @@ -65,6 +65,19 @@ + + + toolBar + + + TopToolBarArea + + + false + + + + Open... @@ -85,6 +98,11 @@ Execute + + + Save strategy + + @@ -152,6 +170,22 @@ + + actionSave_strategy + triggered() + MainWindow + saveStrategy() + + + -1 + -1 + + + 529 + 293 + + + openTrades() @@ -159,5 +193,6 @@ tabCloseRequested(int) newStrategy() executeStrategy() + saveStrategy() diff --git a/ui/strategywidget.ui b/ui/strategywidget.ui index 906a668..e083432 100644 --- a/ui/strategywidget.ui +++ b/ui/strategywidget.ui @@ -6,51 +6,146 @@ 0 0 - 839 - 464 + 977 + 569 Form - + + + 1 + + + 1 + + + 1 + + + 1 + - - - - 0 - 0 - + + + 0 - - Qt::Horizontal - - - - - 0 - 0 - - - - - 1 + + + Code + + + + 1 - - - - - - 0 - 0 - - - - - 300 - 0 - - + + 1 + + + 1 + + + 1 + + + + + Qt::Horizontal + + + + + + + dd.MM.yyyy H:mm + + + + + + + dd.MM.yyyy H:mm + + + + + + + To + + + + + + + All data + + + true + + + + + + + + 0 + 0 + + + + QAbstractItemView::MultiSelection + + + true + + + + 1 + + + + + + + + + 0 + 0 + + + + From + + + + + + + Time window + + + + + + + + + 0 + 0 + + + + + 300 + 0 + + + + + +