diff --git a/build_ui.sh b/build_ui.sh
new file mode 100755
index 0000000..f9351b9
--- /dev/null
+++ b/build_ui.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+/usr/bin/pyuic5 ui/mainwindow.ui > src/nailab/ui_gen/mainwindow.py
+/usr/bin/pyuic5 ui/strategywidget.ui > src/nailab/ui_gen/strategywidget.py
diff --git a/src/nailab/nailab.py b/src/nailab/nailab.py
index 9bd4248..af7b04a 100644
--- a/src/nailab/nailab.py
+++ b/src/nailab/nailab.py
@@ -1,21 +1,19 @@
-import gi
-gi.require_version('Gtk', '3.0')
-gi.require_version('GtkSource', '3.0')
-from gi.repository import Gtk, GObject
-from gi.repository import GtkSource
-
-from nailab.ui.applicationwindow import ApplicationWindow
+import sys
+from PyQt5.QtWidgets import QApplication
+from PyQt5 import QtCore
+from ui.mainwindow import MainWindow
def main():
- GObject.type_register(GtkSource.View)
-
- builder = Gtk.Builder()
- builder.add_from_file('ui/nailab.glade')
-
- ApplicationWindow(builder)
+ QApplication.setOrganizationDomain("kasan.ws")
+ QApplication.setOrganizationName("K.A.S.A.N.")
+ QApplication.setApplicationName("nailab")
+ app = QApplication(sys.argv)
- Gtk.main()
+ wnd = MainWindow()
+ wnd.show()
+
+ return app.exec_()
if __name__ == '__main__':
main()
diff --git a/src/nailab/ui/applicationwindow.py b/src/nailab/ui/applicationwindow.py
deleted file mode 100644
index b964320..0000000
--- a/src/nailab/ui/applicationwindow.py
+++ /dev/null
@@ -1,108 +0,0 @@
-
-from gi.repository import Gtk, GtkSource
-
-from nailab.data.datasource import DataSource
-from nailab.data.datasourcemanager import DataSourceManager
-from nailab.execution.executor import Executor
-from nailab.templates.new_strategy import new_strategy_template
-
-from .resultstable import ResultsTableWidget
-from .tabmanager import TabManager
-
-class ApplicationWindow:
-
- def __init__(self, builder):
- self.window = builder.get_object('ApplicationWindow')
- self.tab_manager = TabManager(builder.get_object('sourceNotebook'))
-
- self._init_tv_datasource(builder)
-
- handlers = {
- 'on_ApplicationWindow_delete_event' : Gtk.main_quit,
- 'on_menuNew' : self.new_file,
- 'on_OpenFile' : self.open_file,
- 'on_menuSave' : self.save_file,
- 'on_menuSaveAs' : self.save_file_as,
- 'on_menuQuit' : Gtk.main_quit,
- 'on_StrategyExecute' : self.strategy_execute
- }
-
- builder.connect_signals(handlers)
- self.window.show_all()
-
- def new_file(self, arg):
- self.tab_manager.new_from_template(new_strategy_template)
-
- def open_file(self, arg):
- dlg = Gtk.FileChooserDialog('Open file', self.window, Gtk.FileChooserAction.OPEN,
- (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
- Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
- result = dlg.run()
-
- if result == Gtk.ResponseType.OK:
- self.tab_manager.new_tab(dlg.get_filename())
-
- dlg.destroy()
-
- def save_file(self, arg):
- self.tab_manager.save_current()
-
- def save_file_as(self, arg):
- dlg = Gtk.FileChooserDialog('Save file', self.window, Gtk.FileChooserAction.SAVE,
- (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
- Gtk.STOCK_SAVE, Gtk.ResponseType.OK))
- result = dlg.run()
-
- if result == Gtk.ResponseType.OK:
- self.tab_manager.save_current_as(dlg.get_filename())
-
- dlg.destroy()
-
- def strategy_execute(self, arg):
- sel = self.tv_datasources.get_selection()
- model, rows = sel.get_selected_rows()
-
- feeds = []
- for row in rows:
- (feed_id, source_name) = self.datasources_store.get(self.datasources_store.get_iter(row), 0, 1)
- source = self.datasourcemanager.get_source(source_name)
- if source is not None:
- feed = source.get_feed(feed_id)
- feeds.append(feed)
-
- e = Executor()
- (result, trades) = e.execute_from_file(self.tab_manager.get_current_source_path(), feeds)
-
- self._add_results_page(result, trades)
-
- def _add_results_page(self, results, trades):
- res_widget = ResultsTableWidget()
- res_widget.set_results(results, trades)
- res_widget.show_all()
- self.tab_manager.new_misc_tab(res_widget)
-
- def _init_tv_datasource(self, builder):
- self.datasourcemanager = DataSourceManager()
- self.datasourcemanager.load_sources()
-
- tv_datasources = builder.get_object('tv_datasources')
- self.tv_datasources = tv_datasources
-
- self.datasources_store = Gtk.TreeStore(str, str)
- for source in self.datasourcemanager.all_sources():
- treeiter = self.datasources_store.append(None, (source.name, source.name))
- for feed in source.available_feeds():
- self.datasources_store.append(treeiter, (feed, source.name))
-
-
- rendererText = Gtk.CellRendererText()
- column = Gtk.TreeViewColumn('Datasources', rendererText, text=0)
- tv_datasources.append_column(column)
-
- tv_datasources.set_model(self.datasources_store)
-
- sel = tv_datasources.get_selection()
- sel.set_mode(Gtk.SelectionMode.MULTIPLE)
-
-
-
diff --git a/src/nailab/ui/equitygraph.py b/src/nailab/ui/equitygraph.py
deleted file mode 100644
index d306b51..0000000
--- a/src/nailab/ui/equitygraph.py
+++ /dev/null
@@ -1,39 +0,0 @@
-
-from gi.repository import Gtk
-
-class EquityGraph(Gtk.Misc):
-
- def __init__(self):
- super().__init__()
- self.trades = []
- self.cumulative_pnl = []
-
- def do_draw(self, cr):
- bg_color = self.get_style_context().get_background_color(Gtk.StateFlags.NORMAL)
- cr.set_source_rgba(*list(bg_color))
- cr.paint()
-
- allocation = self.get_allocation()
- if len(self.cumulative_pnl) > 0:
- fg_color = self.get_style_context().get_color(Gtk.StateFlags.NORMAL)
- cr.set_source_rgba(*list(fg_color));
- cr.set_line_width(2)
-
- min_equity = min(self.cumulative_pnl)
- max_equity = max(self.cumulative_pnl)
-
- kx = allocation.width / len(self.cumulative_pnl)
- ky = 0.8 * allocation.height / (max_equity - min_equity)
-
- cr.move_to(0, allocation.height * 0.9 - (self.cumulative_pnl[0] - min_equity) * ky)
- for i, x in enumerate(self.cumulative_pnl[1:]):
- cr.line_to((i + 1) * kx, allocation.height * 0.9 - (x - min_equity) * ky)
- cr.stroke()
-
- def set_trades(self, trades):
- self.trades = trades
- s = 0
- self.cumulative_pnl = []
- for trade in trades:
- s += trade['pnl']
- self.cumulative_pnl.append(s)
diff --git a/src/nailab/ui/mainwindow.py b/src/nailab/ui/mainwindow.py
new file mode 100644
index 0000000..255d419
--- /dev/null
+++ b/src/nailab/ui/mainwindow.py
@@ -0,0 +1,65 @@
+
+import os
+import importlib
+import importlib.util
+import inspect
+
+from execution.executor import Executor
+from naiback.data.feeds.genericcsvfeed import GenericCSVFeed
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+from PyQt5.Qsci import *
+
+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:]
+
+class MainWindow(QtWidgets.QMainWindow):
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+ self.sources = []
+
+ self.ui = Ui_MainWindow()
+ self.ui.setupUi(self)
+
+ def openTrades(self):
+ pass
+
+ def newStrategy(self):
+ self._makeEditor()
+
+ def openStrategy(self):
+ settings = QtCore.QSettings()
+ filename = QtWidgets.QFileDialog.getOpenFileName(self, self.tr("Select a file..."), settings.value("open_strategy_path"), self.tr("Python (*.py);;All (*.*, *)"))[0]
+ if filename != "":
+ with open(filename, "r") as f:
+ self._makeEditor(filename, os.path.basename(filename), f.read())
+ settings.setValue("open_strategy_path", os.path.dirname(filename))
+
+ def executeStrategy(self):
+ source_file = self.sources[self.ui.tabs.currentIndex()]
+ 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]
+
+
+ def tabCloseRequested(self, tab_index):
+ del self.sources[tab_index]
+ self.ui.tabs.removeTab(tab_index)
+
+ def _makeEditor(self, source_file=None, tab_name="Untitled", content=None):
+ editor = StrategyWidget(self, content)
+ self.sources.append(source_file)
+ self.ui.tabs.addTab(editor, tab_name)
diff --git a/src/nailab/ui/resultstable.py b/src/nailab/ui/resultstable.py
deleted file mode 100644
index b5b705e..0000000
--- a/src/nailab/ui/resultstable.py
+++ /dev/null
@@ -1,59 +0,0 @@
-
-from gi.repository import Gtk
-
-from prettytable import PrettyTable
-
-from .equitygraph import EquityGraph
-
-def render_float(a):
- return "{:.3f}".format(a)
-
-def render_ratio(a, b):
- if b != 0:
- return a / b
- else:
- return "∞"
-
-class ResultsTableWidget(Gtk.Notebook):
-
- def __init__(self):
- super().__init__()
-
- self.set_tab_pos(Gtk.PositionType.LEFT)
-
- self.buffer = Gtk.TextBuffer()
- self.text_result = Gtk.TextView()
- self.text_result.set_buffer(self.buffer)
- self.append_page(self.text_result, Gtk.Label('Statistics'))
-
- self.equity_graph = EquityGraph()
- self.append_page(self.equity_graph, Gtk.Label('Equity'))
-
- style_ctx = self.text_result.get_style_context()
- self.provider = Gtk.CssProvider()
- self.provider.load_from_data(b'GtkTextView { font-family: "Monospace"; }')
- style_ctx.add_provider(self.provider, Gtk.STYLE_PROVIDER_PRIORITY_USER)
-
- def set_results(self, results, trades):
- self.buffer.set_text(self.generate_plain_text(results))
- self.equity_graph.set_trades(trades)
-
- def generate_plain_text(self, stats):
-
- table = PrettyTable()
- table.field_names = ["", "All positions", "Long only", "Short only"]
- table.add_row(["Net profit", render_float(stats['all']['net_profit']), render_float(stats['long']['net_profit']), render_float(stats['short']['net_profit'])])
- table.add_row(["Bars in trade", stats['all']['bars_in_trade'], stats['long']['bars_in_trade'], stats['short']['bars_in_trade']])
- table.add_row(["Profit per bar", render_float(stats['all']['profit_per_bar']), render_float(stats['long']['profit_per_bar']), render_float(stats['short']['profit_per_bar'])])
- table.add_row(["Number of trades", stats['all']['number_of_trades'], stats['long']['number_of_trades'], stats['short']['number_of_trades']])
- table.add_row(["Avg. profit", render_float(stats['all']['avg']), render_float(stats['long']['avg']), render_float(stats['short']['avg'])])
- table.add_row(["Avg. profit, %", render_float(stats['all']['avg_percentage']), render_float(stats['long']['avg_percentage']), render_float(stats['short']['avg_percentage'])])
- table.add_row(["Avg. bars in trade", render_float(stats['all']['avg_bars']), render_float(stats['long']['avg_bars']), render_float(stats['short']['avg_bars'])])
- table.add_row(["Winning trades", stats['all']['won'], stats['long']['won'], stats['short']['won']])
- table.add_row(["Gross profit", render_float(stats['all']['total_won']), render_float(stats['long']['total_won']), render_float(stats['short']['total_won'])])
- table.add_row(["Losing trades", stats['all']['lost'], stats['long']['lost'], stats['short']['lost']])
- table.add_row(["Gross loss", render_float(stats['all']['total_lost']), render_float(stats['long']['total_lost']), render_float(stats['short']['total_lost'])])
- table.add_row(["Profit factor", render_float(stats['all']['profit_factor']), render_float(stats['long']['profit_factor']), render_float(stats['short']['profit_factor'])])
-
- return table.get_string()
-
diff --git a/src/nailab/ui/sourceviewcontroller.py b/src/nailab/ui/sourceviewcontroller.py
deleted file mode 100644
index 2a660f7..0000000
--- a/src/nailab/ui/sourceviewcontroller.py
+++ /dev/null
@@ -1,13 +0,0 @@
-
-class SourceViewController:
-
- def __init__(self, sourceview):
- self.sourceview = sourceview
-
- def set_source_text(self, text):
- self.sourceview.get_buffer().set_text(text)
-
- def get_source_text(self):
- buf = self.sourceview.get_buffer()
- return buf.get_text(buf.get_start_iter(), buf.get_end_iter(), True)
-
diff --git a/src/nailab/ui/strategywidget.py b/src/nailab/ui/strategywidget.py
new file mode 100644
index 0000000..dcfacde
--- /dev/null
+++ b/src/nailab/ui/strategywidget.py
@@ -0,0 +1,28 @@
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+from PyQt5.Qsci import *
+
+from ui_gen.strategywidget import Ui_StrategyWidget
+
+class StrategyWidget(QtWidgets.QWidget):
+
+ def __init__(self, parent=None, content=None):
+ super().__init__(parent)
+
+ self.ui = Ui_StrategyWidget()
+ self.ui.setupUi(self)
+
+ self.ui.splitter.setSizes([20, 80])
+ self.ui.splitter.setStretchFactor(0, 1)
+ self.ui.splitter.setStretchFactor(1, 1)
+
+ font = QtGui.QFont("DejaVu Sans Mono")
+ font.setPointSize(10)
+ self.ui.editor.setFont(font)
+ if content is not None:
+ self.ui.editor.setText(content)
+
+ lexer = QsciLexerPython()
+ lexer.setFont(font)
+ self.ui.editor.setLexer(lexer)
+ self.ui.editor.setUtf8(True)
diff --git a/src/nailab/ui/tabmanager.py b/src/nailab/ui/tabmanager.py
deleted file mode 100644
index f69cd47..0000000
--- a/src/nailab/ui/tabmanager.py
+++ /dev/null
@@ -1,143 +0,0 @@
-
-from gi.repository import GObject, Gtk, GtkSource, Pango
-
-from .sourceviewcontroller import SourceViewController
-
-class TabManager(GObject.Object):
-
- def __init__(self, notebook):
- super().__init__()
- self.notebook = notebook
- self.widgets = {}
- self.source_controllers = {}
- self.id_counter = 1
- self.source_paths = {}
-
- def new_misc_tab(self, widget):
- tab_id = self._next_tab_id()
- self.widgets[tab_id] = widget
- header = Gtk.HBox()
- title_label = Gtk.Label('Result')
- image = Gtk.Image()
- image.set_from_stock(Gtk.STOCK_CLOSE, Gtk.IconSize.MENU)
- close_button = Gtk.Button()
- close_button.set_image(image)
- close_button.set_relief(Gtk.ReliefStyle.NONE)
- close_button.connect('clicked', self.close_cb, tab_id)
-
- header.pack_start(title_label,
- expand=True, fill=True, padding=0)
- header.pack_end(close_button,
- expand=False, fill=False, padding=0)
- header.show_all()
-
- index = self.notebook.append_page(widget, header)
- self.notebook.set_current_page(index)
-
- def _read_source_file(self, source_file):
- if source_file is not None:
- with open(source_file, 'r') as f:
- return f.read()
- else:
- return None
-
-
- def new_tab(self, source_file):
- tab_id = self._next_tab_id()
- (sv, sv_controller) = self._init_sourceeditor()
-
- source = self._read_source_file(source_file)
- if source is not None:
- sv_controller.set_source_text(source)
-
- self.source_paths[tab_id] = source_file
- self.source_controllers[tab_id] = sv_controller
- self.widgets[tab_id] = sv
- sv.show_all()
- header = Gtk.HBox()
- title_label = Gtk.Label(source_file)
- image = Gtk.Image()
- image.set_from_stock(Gtk.STOCK_CLOSE, Gtk.IconSize.MENU)
- close_button = Gtk.Button()
- close_button.set_image(image)
- close_button.set_relief(Gtk.ReliefStyle.NONE)
- close_button.connect('clicked', self.close_cb, tab_id)
-
- header.pack_start(title_label,
- expand=True, fill=True, padding=0)
- header.pack_end(close_button,
- expand=False, fill=False, padding=0)
- header.show_all()
- index = self.notebook.append_page(sv, header)
- self.notebook.set_current_page(index)
- return tab_id
-
- def close_cb(self, arg, tab_id):
- index = self._widget_num_by_tab_id(tab_id)
- self.notebook.remove_page(index)
- del self.widgets[tab_id]
- if tab_id in self.source_paths:
- del self.source_paths[tab_id]
- if tab_id in self.source_controllers:
- del self.source_controllers[tab_id]
-
- def get_current_source_path(self):
- index = self.notebook.get_current_page()
- w = self.notebook.get_nth_page(index)
- for k, v in self.widgets.items():
- if v == w:
- return self.source_paths[k]
-
- return None
-
- def new_from_template(self, template):
- tab_id = self.new_tab(None)
- self.source_controllers[tab_id].set_source_text(template)
-
- def save_current(self):
- index = self.notebook.get_current_page()
- w = self.notebook.get_nth_page(index)
- for k, v in self.widgets.items():
- if v == w:
- text = self.source_controllers[k].get_source_text()
- with open(self.source_paths[k], 'w') as f:
- f.write(text)
-
- def save_current_as(self, path):
- index = self.notebook.get_current_page()
- w = self.notebook.get_nth_page(index)
- for k, v in self.widgets.items():
- if v == w:
- text = self.source_controllers[k].get_source_text()
- with open(path, 'w') as f:
- f.write(text)
-
- def _init_sourceeditor(self):
- scroll = Gtk.ScrolledWindow()
- manager = GtkSource.LanguageManager()
- buf = GtkSource.Buffer()
- buf.set_language(manager.get_language('python'))
- sv = GtkSource.View()
- sv.set_buffer(buf)
- sv.set_monospace(True)
-
- style_ctx = sv.get_style_context()
- self.provider = Gtk.CssProvider()
- self.provider.load_from_data(b'GtkSourceView { font-family: "Monospace"; }')
- style_ctx.add_provider(self.provider, Gtk.STYLE_PROVIDER_PRIORITY_USER)
-
- sourceviewcontroller = SourceViewController(sv)
- scroll.add(sv)
- scroll.show()
-
- return (scroll, sourceviewcontroller)
-
- def _widget_num_by_tab_id(self, tab_id):
- for i in range(0, self.notebook.get_n_pages()):
- if self.widgets[tab_id] == self.notebook.get_nth_page(i):
- return i
- return None
-
- def _next_tab_id(self):
- self.id_counter += 1
- return self.id_counter
diff --git a/src/nailab/ui_gen/__init__.py b/src/nailab/ui_gen/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/src/nailab/ui_gen/mainwindow.py b/src/nailab/ui_gen/mainwindow.py
new file mode 100644
index 0000000..796dae5
--- /dev/null
+++ b/src/nailab/ui_gen/mainwindow.py
@@ -0,0 +1,67 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'ui/mainwindow.ui'
+#
+# Created by: PyQt5 UI code generator 5.5.1
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+
+class Ui_MainWindow(object):
+ def setupUi(self, MainWindow):
+ MainWindow.setObjectName("MainWindow")
+ MainWindow.resize(1050, 712)
+ self.centralwidget = QtWidgets.QWidget(MainWindow)
+ self.centralwidget.setObjectName("centralwidget")
+ self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
+ self.gridLayout.setContentsMargins(3, 3, 3, 3)
+ self.gridLayout.setObjectName("gridLayout")
+ self.tabs = QtWidgets.QTabWidget(self.centralwidget)
+ self.tabs.setTabsClosable(True)
+ self.tabs.setObjectName("tabs")
+ 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.setObjectName("menubar")
+ self.menuFile = QtWidgets.QMenu(self.menubar)
+ self.menuFile.setObjectName("menuFile")
+ self.menuBacktest = QtWidgets.QMenu(self.menubar)
+ self.menuBacktest.setObjectName("menuBacktest")
+ MainWindow.setMenuBar(self.menubar)
+ self.statusbar = QtWidgets.QStatusBar(MainWindow)
+ self.statusbar.setObjectName("statusbar")
+ MainWindow.setStatusBar(self.statusbar)
+ self.actionOpenTrades = QtWidgets.QAction(MainWindow)
+ self.actionOpenTrades.setObjectName("actionOpenTrades")
+ self.actionNew_strategy = QtWidgets.QAction(MainWindow)
+ self.actionNew_strategy.setObjectName("actionNew_strategy")
+ self.actionOpen_strategy = QtWidgets.QAction(MainWindow)
+ self.actionOpen_strategy.setObjectName("actionOpen_strategy")
+ self.actionExecute = QtWidgets.QAction(MainWindow)
+ self.actionExecute.setObjectName("actionExecute")
+ 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.retranslateUi(MainWindow)
+ self.tabs.setCurrentIndex(-1)
+ self.actionOpen_strategy.triggered.connect(MainWindow.openStrategy)
+ self.tabs.tabCloseRequested['int'].connect(MainWindow.tabCloseRequested)
+ self.actionNew_strategy.triggered.connect(MainWindow.newStrategy)
+ self.actionExecute.triggered.connect(MainWindow.executeStrategy)
+ QtCore.QMetaObject.connectSlotsByName(MainWindow)
+
+ def retranslateUi(self, MainWindow):
+ _translate = QtCore.QCoreApplication.translate
+ MainWindow.setWindowTitle(_translate("MainWindow", "Nailab"))
+ self.menuFile.setTitle(_translate("MainWindow", "File"))
+ self.menuBacktest.setTitle(_translate("MainWindow", "Backtest"))
+ 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"))
+
diff --git a/src/nailab/ui_gen/strategywidget.py b/src/nailab/ui_gen/strategywidget.py
new file mode 100644
index 0000000..7f50101
--- /dev/null
+++ b/src/nailab/ui_gen/strategywidget.py
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'ui/strategywidget.ui'
+#
+# Created by: PyQt5 UI code generator 5.5.1
+#
+# WARNING! All changes made in this file will be lost!
+
+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)
+ 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.setOrientation(QtCore.Qt.Horizontal)
+ self.splitter.setObjectName("splitter")
+ self.treeWidget = QtWidgets.QTreeWidget(self.splitter)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Expanding)
+ 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")
+ self.editor = Qsci.QsciScintilla(self.splitter)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.editor.sizePolicy().hasHeightForWidth())
+ self.editor.setSizePolicy(sizePolicy)
+ self.editor.setMinimumSize(QtCore.QSize(300, 0))
+ self.editor.setObjectName("editor")
+ self.gridLayout.addWidget(self.splitter, 0, 0, 1, 1)
+
+ self.retranslateUi(StrategyWidget)
+ QtCore.QMetaObject.connectSlotsByName(StrategyWidget)
+
+ def retranslateUi(self, StrategyWidget):
+ _translate = QtCore.QCoreApplication.translate
+ StrategyWidget.setWindowTitle(_translate("StrategyWidget", "Form"))
+
+from PyQt5 import Qsci
diff --git a/ui/mainwindow.ui b/ui/mainwindow.ui
new file mode 100644
index 0000000..8a95fc9
--- /dev/null
+++ b/ui/mainwindow.ui
@@ -0,0 +1,163 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 1050
+ 712
+
+
+
+ Nailab
+
+
+
+
+ 3
+
+
+ 3
+
+
+ 3
+
+
+ 3
+
+ -
+
+
+ -1
+
+
+ true
+
+
+
+
+
+
+
+
+
+ Open...
+
+
+
+
+ New strategy
+
+
+
+
+ Open strategy
+
+
+
+
+ Execute
+
+
+
+
+
+
+ actionOpen_strategy
+ triggered()
+ MainWindow
+ openStrategy()
+
+
+ -1
+ -1
+
+
+ 524
+ 355
+
+
+
+
+ tabs
+ tabCloseRequested(int)
+ MainWindow
+ tabCloseRequested(int)
+
+
+ 481
+ 335
+
+
+ 1049
+ 99
+
+
+
+
+ actionNew_strategy
+ triggered()
+ MainWindow
+ newStrategy()
+
+
+ -1
+ -1
+
+
+ 524
+ 355
+
+
+
+
+ actionExecute
+ triggered()
+ MainWindow
+ executeStrategy()
+
+
+ -1
+ -1
+
+
+ 524
+ 355
+
+
+
+
+
+ openTrades()
+ openStrategy()
+ tabCloseRequested(int)
+ newStrategy()
+ executeStrategy()
+
+
diff --git a/ui/nailab.glade b/ui/nailab.glade
deleted file mode 100644
index 11e5d65..0000000
--- a/ui/nailab.glade
+++ /dev/null
@@ -1,246 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/ui/strategywidget.ui b/ui/strategywidget.ui
new file mode 100644
index 0000000..906a668
--- /dev/null
+++ b/ui/strategywidget.ui
@@ -0,0 +1,69 @@
+
+
+ StrategyWidget
+
+
+
+ 0
+ 0
+ 839
+ 464
+
+
+
+ Form
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Qt::Horizontal
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 1
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 300
+ 0
+
+
+
+
+
+
+
+
+
+ QsciScintilla
+ QWidget
+
+ 1
+
+
+
+
+