15 changed files with 458 additions and 622 deletions
@ -0,0 +1,4 @@
@@ -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 |
||||
@ -1,21 +1,19 @@
@@ -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() |
||||
|
||||
@ -1,108 +0,0 @@
@@ -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) |
||||
|
||||
|
||||
|
||||
@ -1,39 +0,0 @@
@@ -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) |
||||
@ -0,0 +1,65 @@
@@ -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) |
||||
@ -1,59 +0,0 @@
@@ -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() |
||||
|
||||
@ -1,13 +0,0 @@
@@ -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) |
||||
|
||||
@ -0,0 +1,28 @@
@@ -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) |
||||
@ -1,143 +0,0 @@
@@ -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 |
||||
@ -0,0 +1,67 @@
@@ -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")) |
||||
|
||||
@ -0,0 +1,50 @@
@@ -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 |
||||
@ -0,0 +1,163 @@
@@ -0,0 +1,163 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<ui version="4.0"> |
||||
<class>MainWindow</class> |
||||
<widget class="QMainWindow" name="MainWindow"> |
||||
<property name="geometry"> |
||||
<rect> |
||||
<x>0</x> |
||||
<y>0</y> |
||||
<width>1050</width> |
||||
<height>712</height> |
||||
</rect> |
||||
</property> |
||||
<property name="windowTitle"> |
||||
<string>Nailab</string> |
||||
</property> |
||||
<widget class="QWidget" name="centralwidget"> |
||||
<layout class="QGridLayout" name="gridLayout"> |
||||
<property name="leftMargin"> |
||||
<number>3</number> |
||||
</property> |
||||
<property name="topMargin"> |
||||
<number>3</number> |
||||
</property> |
||||
<property name="rightMargin"> |
||||
<number>3</number> |
||||
</property> |
||||
<property name="bottomMargin"> |
||||
<number>3</number> |
||||
</property> |
||||
<item row="0" column="0"> |
||||
<widget class="QTabWidget" name="tabs"> |
||||
<property name="currentIndex"> |
||||
<number>-1</number> |
||||
</property> |
||||
<property name="tabsClosable"> |
||||
<bool>true</bool> |
||||
</property> |
||||
</widget> |
||||
</item> |
||||
</layout> |
||||
</widget> |
||||
<widget class="QMenuBar" name="menubar"> |
||||
<property name="geometry"> |
||||
<rect> |
||||
<x>0</x> |
||||
<y>0</y> |
||||
<width>1050</width> |
||||
<height>23</height> |
||||
</rect> |
||||
</property> |
||||
<widget class="QMenu" name="menuFile"> |
||||
<property name="title"> |
||||
<string>File</string> |
||||
</property> |
||||
<addaction name="actionNew_strategy"/> |
||||
<addaction name="actionOpen_strategy"/> |
||||
</widget> |
||||
<widget class="QMenu" name="menuBacktest"> |
||||
<property name="title"> |
||||
<string>Backtest</string> |
||||
</property> |
||||
<addaction name="actionExecute"/> |
||||
</widget> |
||||
<addaction name="menuFile"/> |
||||
<addaction name="menuBacktest"/> |
||||
</widget> |
||||
<widget class="QStatusBar" name="statusbar"/> |
||||
<action name="actionOpenTrades"> |
||||
<property name="text"> |
||||
<string>Open...</string> |
||||
</property> |
||||
</action> |
||||
<action name="actionNew_strategy"> |
||||
<property name="text"> |
||||
<string>New strategy</string> |
||||
</property> |
||||
</action> |
||||
<action name="actionOpen_strategy"> |
||||
<property name="text"> |
||||
<string>Open strategy</string> |
||||
</property> |
||||
</action> |
||||
<action name="actionExecute"> |
||||
<property name="text"> |
||||
<string>Execute</string> |
||||
</property> |
||||
</action> |
||||
</widget> |
||||
<resources/> |
||||
<connections> |
||||
<connection> |
||||
<sender>actionOpen_strategy</sender> |
||||
<signal>triggered()</signal> |
||||
<receiver>MainWindow</receiver> |
||||
<slot>openStrategy()</slot> |
||||
<hints> |
||||
<hint type="sourcelabel"> |
||||
<x>-1</x> |
||||
<y>-1</y> |
||||
</hint> |
||||
<hint type="destinationlabel"> |
||||
<x>524</x> |
||||
<y>355</y> |
||||
</hint> |
||||
</hints> |
||||
</connection> |
||||
<connection> |
||||
<sender>tabs</sender> |
||||
<signal>tabCloseRequested(int)</signal> |
||||
<receiver>MainWindow</receiver> |
||||
<slot>tabCloseRequested(int)</slot> |
||||
<hints> |
||||
<hint type="sourcelabel"> |
||||
<x>481</x> |
||||
<y>335</y> |
||||
</hint> |
||||
<hint type="destinationlabel"> |
||||
<x>1049</x> |
||||
<y>99</y> |
||||
</hint> |
||||
</hints> |
||||
</connection> |
||||
<connection> |
||||
<sender>actionNew_strategy</sender> |
||||
<signal>triggered()</signal> |
||||
<receiver>MainWindow</receiver> |
||||
<slot>newStrategy()</slot> |
||||
<hints> |
||||
<hint type="sourcelabel"> |
||||
<x>-1</x> |
||||
<y>-1</y> |
||||
</hint> |
||||
<hint type="destinationlabel"> |
||||
<x>524</x> |
||||
<y>355</y> |
||||
</hint> |
||||
</hints> |
||||
</connection> |
||||
<connection> |
||||
<sender>actionExecute</sender> |
||||
<signal>triggered()</signal> |
||||
<receiver>MainWindow</receiver> |
||||
<slot>executeStrategy()</slot> |
||||
<hints> |
||||
<hint type="sourcelabel"> |
||||
<x>-1</x> |
||||
<y>-1</y> |
||||
</hint> |
||||
<hint type="destinationlabel"> |
||||
<x>524</x> |
||||
<y>355</y> |
||||
</hint> |
||||
</hints> |
||||
</connection> |
||||
</connections> |
||||
<slots> |
||||
<slot>openTrades()</slot> |
||||
<slot>openStrategy()</slot> |
||||
<slot>tabCloseRequested(int)</slot> |
||||
<slot>newStrategy()</slot> |
||||
<slot>executeStrategy()</slot> |
||||
</slots> |
||||
</ui> |
||||
@ -1,246 +0,0 @@
@@ -1,246 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!-- Generated with glade 3.18.3 --> |
||||
<interface> |
||||
<requires lib="gtk+" version="3.0"/> |
||||
<object class="GtkImage" id="image1"> |
||||
<property name="visible">True</property> |
||||
<property name="can_focus">False</property> |
||||
<property name="stock">gtk-missing-image</property> |
||||
</object> |
||||
<object class="GtkListStore" id="model_dataSources"/> |
||||
<object class="GtkApplicationWindow" id="ApplicationWindow"> |
||||
<property name="width_request">1024</property> |
||||
<property name="height_request">768</property> |
||||
<property name="can_focus">False</property> |
||||
<property name="margin_bottom">2</property> |
||||
<signal name="delete-event" handler="on_ApplicationWindow_delete_event" swapped="no"/> |
||||
<child> |
||||
<object class="GtkFrame" id="frame1"> |
||||
<property name="visible">True</property> |
||||
<property name="can_focus">False</property> |
||||
<property name="label_xalign">0</property> |
||||
<property name="shadow_type">none</property> |
||||
<child> |
||||
<object class="GtkPaned" id="paned1"> |
||||
<property name="visible">True</property> |
||||
<property name="can_focus">True</property> |
||||
<property name="position">200</property> |
||||
<property name="position_set">True</property> |
||||
<child> |
||||
<object class="GtkScrolledWindow" id="scrolledwindow1"> |
||||
<property name="visible">True</property> |
||||
<property name="can_focus">True</property> |
||||
<property name="shadow_type">in</property> |
||||
<child> |
||||
<object class="GtkTreeView" id="tv_datasources"> |
||||
<property name="visible">True</property> |
||||
<property name="can_focus">True</property> |
||||
<property name="hscroll_policy">natural</property> |
||||
<property name="vscroll_policy">natural</property> |
||||
<property name="model">model_dataSources</property> |
||||
<property name="rubber_banding">True</property> |
||||
<property name="enable_grid_lines">both</property> |
||||
<child internal-child="selection"> |
||||
<object class="GtkTreeSelection" id="treeview-selection1"/> |
||||
</child> |
||||
</object> |
||||
</child> |
||||
</object> |
||||
<packing> |
||||
<property name="resize">False</property> |
||||
<property name="shrink">True</property> |
||||
</packing> |
||||
</child> |
||||
<child> |
||||
<object class="GtkNotebook" id="sourceNotebook"> |
||||
<property name="visible">True</property> |
||||
<property name="can_focus">True</property> |
||||
<child> |
||||
<placeholder/> |
||||
</child> |
||||
<child type="tab"> |
||||
<placeholder/> |
||||
</child> |
||||
<child> |
||||
<placeholder/> |
||||
</child> |
||||
<child type="tab"> |
||||
<placeholder/> |
||||
</child> |
||||
<child> |
||||
<placeholder/> |
||||
</child> |
||||
<child type="tab"> |
||||
<placeholder/> |
||||
</child> |
||||
</object> |
||||
<packing> |
||||
<property name="resize">True</property> |
||||
<property name="shrink">True</property> |
||||
</packing> |
||||
</child> |
||||
</object> |
||||
</child> |
||||
<child type="label"> |
||||
<object class="GtkMenuBar" id="menubar3"> |
||||
<property name="visible">True</property> |
||||
<property name="can_focus">False</property> |
||||
<child> |
||||
<object class="GtkMenuItem" id="menuitem9"> |
||||
<property name="visible">True</property> |
||||
<property name="can_focus">False</property> |
||||
<property name="label" translatable="yes">_Файл</property> |
||||
<property name="use_underline">True</property> |
||||
<child type="submenu"> |
||||
<object class="GtkMenu" id="menu7"> |
||||
<property name="visible">True</property> |
||||
<property name="can_focus">False</property> |
||||
<child> |
||||
<object class="GtkImageMenuItem" id="menuNew"> |
||||
<property name="label">gtk-new</property> |
||||
<property name="visible">True</property> |
||||
<property name="can_focus">False</property> |
||||
<property name="use_underline">True</property> |
||||
<property name="use_stock">True</property> |
||||
<signal name="activate" handler="on_menuNew" swapped="no"/> |
||||
</object> |
||||
</child> |
||||
<child> |
||||
<object class="GtkImageMenuItem" id="menuOpen"> |
||||
<property name="label">gtk-open</property> |
||||
<property name="visible">True</property> |
||||
<property name="can_focus">False</property> |
||||
<property name="use_underline">True</property> |
||||
<property name="use_stock">True</property> |
||||
<signal name="activate" handler="on_OpenFile" swapped="no"/> |
||||
</object> |
||||
</child> |
||||
<child> |
||||
<object class="GtkImageMenuItem" id="menuSave"> |
||||
<property name="label">gtk-save</property> |
||||
<property name="visible">True</property> |
||||
<property name="can_focus">False</property> |
||||
<property name="use_underline">True</property> |
||||
<property name="use_stock">True</property> |
||||
<signal name="activate" handler="on_menuSave" swapped="no"/> |
||||
</object> |
||||
</child> |
||||
<child> |
||||
<object class="GtkImageMenuItem" id="menuSaveAs"> |
||||
<property name="label">gtk-save-as</property> |
||||
<property name="visible">True</property> |
||||
<property name="can_focus">False</property> |
||||
<property name="use_underline">True</property> |
||||
<property name="use_stock">True</property> |
||||
<signal name="activate" handler="on_menuSaveAs" swapped="no"/> |
||||
</object> |
||||
</child> |
||||
<child> |
||||
<object class="GtkSeparatorMenuItem" id="separatormenuitem3"> |
||||
<property name="visible">True</property> |
||||
<property name="can_focus">False</property> |
||||
</object> |
||||
</child> |
||||
<child> |
||||
<object class="GtkImageMenuItem" id="menuQuit"> |
||||
<property name="label">gtk-quit</property> |
||||
<property name="visible">True</property> |
||||
<property name="can_focus">False</property> |
||||
<property name="use_underline">True</property> |
||||
<property name="use_stock">True</property> |
||||
<signal name="activate" handler="on_menuQuit" swapped="no"/> |
||||
</object> |
||||
</child> |
||||
</object> |
||||
</child> |
||||
</object> |
||||
</child> |
||||
<child> |
||||
<object class="GtkMenuItem" id="menuitem10"> |
||||
<property name="visible">True</property> |
||||
<property name="can_focus">False</property> |
||||
<property name="label" translatable="yes">_Правка</property> |
||||
<property name="use_underline">True</property> |
||||
<child type="submenu"> |
||||
<object class="GtkMenu" id="menu8"> |
||||
<property name="visible">True</property> |
||||
<property name="can_focus">False</property> |
||||
<child> |
||||
<object class="GtkImageMenuItem" id="imagemenuitem26"> |
||||
<property name="label">gtk-cut</property> |
||||
<property name="visible">True</property> |
||||
<property name="can_focus">False</property> |
||||
<property name="use_underline">True</property> |
||||
<property name="use_stock">True</property> |
||||
</object> |
||||
</child> |
||||
<child> |
||||
<object class="GtkImageMenuItem" id="imagemenuitem27"> |
||||
<property name="label">gtk-copy</property> |
||||
<property name="visible">True</property> |
||||
<property name="can_focus">False</property> |
||||
<property name="use_underline">True</property> |
||||
<property name="use_stock">True</property> |
||||
</object> |
||||
</child> |
||||
<child> |
||||
<object class="GtkImageMenuItem" id="imagemenuitem28"> |
||||
<property name="label">gtk-paste</property> |
||||
<property name="visible">True</property> |
||||
<property name="can_focus">False</property> |
||||
<property name="use_underline">True</property> |
||||
<property name="use_stock">True</property> |
||||
</object> |
||||
</child> |
||||
<child> |
||||
<object class="GtkImageMenuItem" id="imagemenuitem29"> |
||||
<property name="label">gtk-delete</property> |
||||
<property name="visible">True</property> |
||||
<property name="can_focus">False</property> |
||||
<property name="use_underline">True</property> |
||||
<property name="use_stock">True</property> |
||||
</object> |
||||
</child> |
||||
</object> |
||||
</child> |
||||
</object> |
||||
</child> |
||||
<child> |
||||
<object class="GtkMenuItem" id="menuitem11"> |
||||
<property name="visible">True</property> |
||||
<property name="can_focus">False</property> |
||||
<property name="label" translatable="yes">_Вид</property> |
||||
<property name="use_underline">True</property> |
||||
</object> |
||||
</child> |
||||
<child> |
||||
<object class="GtkMenuItem" id="menuitem1"> |
||||
<property name="visible">True</property> |
||||
<property name="can_focus">False</property> |
||||
<property name="label" translatable="yes">Strategy</property> |
||||
<property name="use_underline">True</property> |
||||
<child type="submenu"> |
||||
<object class="GtkMenu" id="menu1"> |
||||
<property name="visible">True</property> |
||||
<property name="can_focus">False</property> |
||||
<child> |
||||
<object class="GtkImageMenuItem" id="menuExecute"> |
||||
<property name="label" translatable="yes">Execute |
||||
</property> |
||||
<property name="visible">True</property> |
||||
<property name="can_focus">False</property> |
||||
<property name="image">image1</property> |
||||
<property name="use_stock">False</property> |
||||
<signal name="activate" handler="on_StrategyExecute" swapped="no"/> |
||||
</object> |
||||
</child> |
||||
</object> |
||||
</child> |
||||
</object> |
||||
</child> |
||||
</object> |
||||
</child> |
||||
</object> |
||||
</child> |
||||
</object> |
||||
</interface> |
||||
@ -0,0 +1,69 @@
@@ -0,0 +1,69 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<ui version="4.0"> |
||||
<class>StrategyWidget</class> |
||||
<widget class="QWidget" name="StrategyWidget"> |
||||
<property name="geometry"> |
||||
<rect> |
||||
<x>0</x> |
||||
<y>0</y> |
||||
<width>839</width> |
||||
<height>464</height> |
||||
</rect> |
||||
</property> |
||||
<property name="windowTitle"> |
||||
<string>Form</string> |
||||
</property> |
||||
<layout class="QGridLayout" name="gridLayout"> |
||||
<item row="0" column="0"> |
||||
<widget class="QSplitter" name="splitter"> |
||||
<property name="sizePolicy"> |
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred"> |
||||
<horstretch>0</horstretch> |
||||
<verstretch>0</verstretch> |
||||
</sizepolicy> |
||||
</property> |
||||
<property name="orientation"> |
||||
<enum>Qt::Horizontal</enum> |
||||
</property> |
||||
<widget class="QTreeWidget" name="treeWidget"> |
||||
<property name="sizePolicy"> |
||||
<sizepolicy hsizetype="Maximum" vsizetype="Expanding"> |
||||
<horstretch>0</horstretch> |
||||
<verstretch>0</verstretch> |
||||
</sizepolicy> |
||||
</property> |
||||
<column> |
||||
<property name="text"> |
||||
<string notr="true">1</string> |
||||
</property> |
||||
</column> |
||||
</widget> |
||||
<widget class="QsciScintilla" name="editor" native="true"> |
||||
<property name="sizePolicy"> |
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred"> |
||||
<horstretch>0</horstretch> |
||||
<verstretch>0</verstretch> |
||||
</sizepolicy> |
||||
</property> |
||||
<property name="minimumSize"> |
||||
<size> |
||||
<width>300</width> |
||||
<height>0</height> |
||||
</size> |
||||
</property> |
||||
</widget> |
||||
</widget> |
||||
</item> |
||||
</layout> |
||||
</widget> |
||||
<customwidgets> |
||||
<customwidget> |
||||
<class>QsciScintilla</class> |
||||
<extends>QWidget</extends> |
||||
<header location="global">qsciscintilla.h</header> |
||||
<container>1</container> |
||||
</customwidget> |
||||
</customwidgets> |
||||
<resources/> |
||||
<connections/> |
||||
</ui> |
||||
Loading…
Reference in new issue