diff --git a/QTVisual/Plot.py b/QTVisual/Plot.py index 4b3ad70..18867dc 100644 --- a/QTVisual/Plot.py +++ b/QTVisual/Plot.py @@ -19,7 +19,7 @@ class PlotPanel(pg.PlotWidget): # fix axes decimals https://stackoverflow.com/questions/59768880/how-to-format-y-axis-displayed-numbers-in-pyqtgraph def __init__(self,df:Type[pd.DataFrame],colors = None, types = None): super().__init__() - self.palette = ('b', 'g', 'r', 'c', 'm', 'y')#, 'k', 'w') + self.palette = ('b', 'g', 'r', 'c', 'm', 'y','w')#, 'k', 'w') self.colors = {series_name:self.palette[i%len(self.palette)] for i,series_name in enumerate(df)} if colors is None else colors self.df = df self.indicators = {} # Dict{plot} diff --git a/indicatorplayground.ipynb b/indicatorplayground.ipynb index 06d27d1..20fc2f3 100644 --- a/indicatorplayground.ipynb +++ b/indicatorplayground.ipynb @@ -2,201 +2,86 @@ "cells": [ { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "source": [ "import sys\n", - "from PyQt5.QtWidgets import QApplication, QMainWindow, QHBoxLayout, QVBoxLayout, QWidget\n", - "\n", - "from QTVisual.PlotsHolder import PGFigureLayoutWrap\n", - "from QTVisual.Plot import PlotPanel\n", - "#from QTVisual.utils import plotloader\n", - "\n", - "def getOHLC_pickle(pklpath):\n", - " import pickle\n", - " with open(pklpath,'rb') as f:\n", - " data = pickle.load(f)\n", - " return data\n", - "def getOHLC_raw(to_pickle=False):\n", - " from DataManipulation.DataHandler import mergeMonths, DemaMinDayMultinom\n", - " import pandas as pd\n", - " from torch.utils.data import ConcatDataset\n", - " #data = mergePeriod(1,4,beg=\"DAT_ASCII_EURUSD_M1_2021\",dir=\"./eurusd2021/\",dump=False)\n", - " data2021 = mergeMonths(start=1, end=9,beg=\"DAT_ASCII_EURUSD_M1_2021\",dir = './Data/eurusd2021/', dump=False)\n", - "\n", - " dir = \"./Data/\"\n", - " beg = \"DAT_ASCII_EURUSD_M1_\"\n", - "\n", - " years = range(2010,2021)\n", - " dataY = []\n", - " for y in years:\n", - " dataY.append(pd.read_csv(dir+beg+str(y)+'.csv',sep=';',names = ['Open','High','Low','Close','Volume']))\n", - " dataY.append(data2021)\n", - " data = pd.concat(dataY)\n", - " data.index.name = \"Date\"\n", - " data.index = pd.to_datetime(data.index)\n", - " if to_pickle:\n", - " import pickle\n", - " with open('OHLC.pkl','wb') as f:\n", - " pickle.dump(data,f,protocol=pickle.HIGHEST_PROTOCOL)\n", - " return data\n", - "\n", - "\n", - "\n", - "class MainWindow(QMainWindow):\n", - "\n", - " def __init__(self, picklepath = None, dfs = None):\n", - " super(MainWindow, self).__init__()\n", - "\n", - " self.setWindowTitle(\"My App\")\n", - " self.layout = QHBoxLayout()\n", - " \n", - " self.leftbar = QVBoxLayout()\n", - " \n", - " if picklepath is None:\n", - " self.plotpanels,self.data = Test2Plots()\n", - " elif dfs is None:\n", - " self.dfs = getOHLC_pickle(picklepath)\n", - " self.data = self.dfs[0]\n", - " self.plotpanels = [PlotPanel(df) for df in self.dfs]\n", - " else:\n", - " self.dfs = dfs\n", - " self.data = self.dfs[0]\n", - " self.plotpanels = [PlotPanel(df) for df in self.dfs]\n", - " #print(self.data.tail(100))\n", - " self.rightmain = PGFigureLayoutWrap(self.plotpanels, len(self.data))\n", - " self.layout.addLayout(self.leftbar)\n", - " self.layout.addLayout(self.rightmain)\n", - "\n", - " widget = QWidget()\n", - " widget.setLayout(self.layout)\n", - " self.setCentralWidget(widget)\n", - "def Test1Plots():\n", - " from DataManipulation.indicators import DEMA,MYEMA,D1\n", - " from time import time\n", - " t = time()\n", - " data = getOHLC_pickle(\"EURUSD_M_2010_2021.pkl\")\n", - " # 9min\n", - " demaperiod = [9]\n", - " # 100 min, 200 min, 5 h, 40 h, 80 h, 100 h, 300 h, 100 d, 200 d\n", - " # 1.6d, 3.3d, 4.16d, 12.5d, \n", - " emaperiod = [100,200,300,2400,4800, 100*60,300*60,2400*60,4800*60]\n", - " for p in demaperiod:\n", - " data['dema'+str(p)] = DEMA(data['Close'],p)\n", - " for p in emaperiod:\n", - " data['ema'+str(p)] = MYEMA(data['Close'],p)\n", - " D1demaperiod = [9]\n", - " D1emaperiod = [100,200,300,2400,4800]\n", - " for p in D1demaperiod:\n", - " data['D1dema'+str(p)] = D1(data['dema'+str(p)])\n", - " for p in D1emaperiod:\n", - " data['D1ema'+str(p)] = D1(data['ema'+str(p)])\n", - "\n", - " stdPeriod = [9,100,300,100*60]\n", - " stdInd = ['D1dema9']#,'D1ema100','D1ema300']\n", - " for p in stdPeriod:\n", - " for i in stdInd:\n", - " data[i+\"_std\"+str(p)] = data[i].rolling(p).std()\n", - " print(data.columns)\n", - " print(time()-t)\n", - " t = time()\n", - " plotpanels = [\n", - " PlotPanel(\n", - " data[['Close']+['dema'+str(p) for p in demaperiod]+['ema'+str(p) for p in emaperiod]],\n", - " ),\n", - " PlotPanel(\n", - " data[['D1dema'+str(p) for p in D1demaperiod]+['D1ema'+str(p) for p in D1emaperiod]]\n", - " ),\n", - " PlotPanel(\n", - " data[['D1dema9_std'+str(p) for p in stdPeriod]]\n", - " )\n", - " ]\n", - " return plotpanels,data\n", - "\n", - "def Test2Plots():\n", - " from DataManipulation.indicators import DEMA,MYEMA,D1\n", - " from time import time\n", - " t = time()\n", - " mdata = getOHLC_pickle(\"EURUSD_M_2010_2021.pkl\")\n", - " data = mdata.resample('1H').agg({'Open': 'first', \n", - " 'High': 'max', \n", - " 'Low': 'min', \n", - " 'Close': 'last'}).dropna()\n", - " # 9min\n", - " demaperiod = [9]\n", - " # 100 min, 200 min, 5 h, 40 h, 80 h, 100 h, 300 h, 100 d, 200 d\n", - " # 1.6d, 3.3d, 4.16d, 12.5d, \n", - " emaperiod = [100,200,300,2400,4800, 100*60,300*60,2400*60,4800*60]\n", - " for p in demaperiod:\n", - " data['dema'+str(p)] = DEMA(data['Close'],p)\n", - " for p in emaperiod:\n", - " data['ema'+str(p)] = MYEMA(data['Close'],p)\n", - " D1demaperiod = [9]\n", - " D1emaperiod = [100,200,300,2400,4800]\n", - " for p in D1demaperiod:\n", - " data['D1dema'+str(p)] = D1(data['dema'+str(p)])\n", - " for p in D1emaperiod:\n", - " data['D1ema'+str(p)] = D1(data['ema'+str(p)])\n", - "\n", - " stdPeriod = [9,100,300,100*60]\n", - " stdInd = ['D1dema9','dema9']#,'D1ema100','D1ema300']\n", - " for p in stdPeriod:\n", - " for i in stdInd:\n", - " data[i+\"_std\"+str(p)] = data[i].rolling(p).std()\n", - " \n", - " print(data.columns)\n", - " print(time()-t)\n", - " t = time()\n", - " plotpanels = [\n", - " PlotPanel(\n", - " data[['Close']+['dema'+str(p) for p in demaperiod]+['ema'+str(p) for p in emaperiod]],\n", - " ),\n", - " PlotPanel(\n", - " data[['D1dema'+str(p) for p in D1demaperiod]+['D1ema'+str(p) for p in D1emaperiod]]\n", - " ),\n", - " PlotPanel(\n", - " data[['D1dema9_std'+str(p) for p in stdPeriod]]\n", - " ),\n", - " PlotPanel(\n", - " data[['dema9_std'+str(p) for p in stdPeriod]]\n", - " )\n", - " ]\n", - " return plotpanels,data\n", - "\n", - "\n", - "app = QApplication(sys.argv)\n", - "\n", + "from newqt import MainWindow, QApplication\n", + "app = QApplication(sys.argv) \n", "window = MainWindow()\n", "window.show()\n", - "\n", "app.exec() " ], "outputs": [ { - "output_type": "stream", - "name": "stderr", - "text": [ - "QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-sean'\n" + "output_type": "error", + "ename": "Error", + "evalue": "Session cannot generate requests", + "traceback": [ + "Error: Session cannot generate requests", + "at w.executeCodeCell (/home/sean/.vscode-server/extensions/ms-toolsai.jupyter-2021.8.1236758218/out/client/extension.js:90:327199)", + "at w.execute (/home/sean/.vscode-server/extensions/ms-toolsai.jupyter-2021.8.1236758218/out/client/extension.js:90:326520)", + "at w.start (/home/sean/.vscode-server/extensions/ms-toolsai.jupyter-2021.8.1236758218/out/client/extension.js:90:322336)", + "at runMicrotasks ()", + "at processTicksAndRejections (internal/process/task_queues.js:93:5)", + "at async t.CellExecutionQueue.executeQueuedCells (/home/sean/.vscode-server/extensions/ms-toolsai.jupyter-2021.8.1236758218/out/client/extension.js:90:336863)", + "at async t.CellExecutionQueue.start (/home/sean/.vscode-server/extensions/ms-toolsai.jupyter-2021.8.1236758218/out/client/extension.js:90:336403)" ] - }, + } + ], + "metadata": {} + }, + { + "cell_type": "code", + "execution_count": 1, + "source": [ + "from DataManipulation.indicators import DEMA,MYEMA,D1\n", + "from QTVisual.Plot import PlotPanel\n", + "from newqt import getOHLC_pickle\n", + "from time import time\n", + "t = time()\n", + "mdata = getOHLC_pickle(\"EURUSD_M_2010_2021.pkl\")\n", + "data = mdata.resample('1H').agg({'Open': 'first', \n", + " 'High': 'max', \n", + " 'Low': 'min', \n", + " 'Close': 'last'}).dropna()\n", + "# 9min\n", + "demaperiod = 9\n", + "\n", + "data[\"dema9_Hi\"] = DEMA(data['High'],demaperiod)\n", + "data[\"dema9_Lo\"] = DEMA(data['Low'],demaperiod)\n", + "data[\"dema9_Cl\"] = DEMA(data['Open'],demaperiod)\n", + "\n", + "\n", + "print(data.columns)\n", + "print(time()-t)\n", + "t = time()\n", + "#plotpanels = [\n", + "# PlotPanel(\n", + "# data[[\"Open\",\"High\",\"Low\",\"Close\"]],\n", + "# )\n", + "#]\n", + "#return plotpanels,data\n", + "import sys\n", + "from newqt import MainWindow, QApplication\n", + "app = QApplication(sys.argv) \n", + "window = MainWindow(dfs = [data[[\"Open\",\"High\",\"Low\",\"Close\",\"dema9_Hi\",\"dema9_Lo\",\"dema9_Cl\"]]])\n", + "window.show()\n", + "app.exec() \n" + ], + "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ - "Index(['Open', 'High', 'Low', 'Close', 'dema9', 'ema100', 'ema200', 'ema300',\n", - " 'ema2400', 'ema4800', 'ema6000', 'ema18000', 'ema144000', 'ema288000',\n", - " 'D1dema9', 'D1ema100', 'D1ema200', 'D1ema300', 'D1ema2400', 'D1ema4800',\n", - " 'D1dema9_std9', 'dema9_std9', 'D1dema9_std100', 'dema9_std100',\n", - " 'D1dema9_std300', 'dema9_std300', 'D1dema9_std6000', 'dema9_std6000'],\n", - " dtype='object')\n", - "5.127691984176636\n" + "Index(['Open', 'High', 'Low', 'Close', 'dema9_Hi', 'dema9_Lo', 'dema9_Cl'], dtype='object')\n", + "1.4156897068023682\n" ] }, { "output_type": "stream", "name": "stderr", "text": [ - "/home/sean/miniconda3/envs/qttrade/lib/python3.9/site-packages/pyqtgraph/graphicsItems/PlotCurveItem.py:153: RuntimeWarning: All-NaN slice encountered\n", - " b = (np.nanmin(d), np.nanmax(d))\n", + "QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-sean'\n", "libGL error: No matching fbConfigs or visuals found\n", "libGL error: failed to load driver: swrast\n" ] @@ -209,7 +94,89 @@ ] }, "metadata": {}, - "execution_count": 2 + "execution_count": 1 + } + ], + "metadata": {} + }, + { + "cell_type": "code", + "execution_count": 1, + "source": [ + "x=1" + ], + "outputs": [], + "metadata": {} + }, + { + "cell_type": "code", + "execution_count": 1, + "source": [ + "import pyqtgraph as pg\n", + "from pyqtgraph import QtCore, QtGui\n", + "\n", + "## Create a subclass of GraphicsObject.\n", + "## The only required methods are paint() and boundingRect() \n", + "## (see QGraphicsItem documentation)\n", + "class CandlestickItem(pg.GraphicsObject):\n", + " def __init__(self, data):\n", + " pg.GraphicsObject.__init__(self)\n", + " self.data = data ## data must have fields: time, open, close, min, max\n", + " self.generatePicture()\n", + " \n", + " def generatePicture(self):\n", + " ## pre-computing a QPicture object allows paint() to run much more quickly, \n", + " ## rather than re-drawing the shapes every time.\n", + " self.picture = QtGui.QPicture()\n", + " p = QtGui.QPainter(self.picture)\n", + " p.setPen(pg.mkPen('w'))\n", + " w = (self.data[1][0] - self.data[0][0]) / 3.\n", + " for (t, open, close, min, max) in self.data:\n", + " p.drawLine(QtCore.QPointF(t, min), QtCore.QPointF(t, max))\n", + " if open > close:\n", + " p.setBrush(pg.mkBrush('r'))\n", + " else:\n", + " p.setBrush(pg.mkBrush('g'))\n", + " p.drawRect(QtCore.QRectF(t-w, open, w*2, close-open))\n", + " p.end()\n", + " \n", + " def paint(self, p, *args):\n", + " p.drawPicture(0, 0, self.picture)\n", + " \n", + " def boundingRect(self):\n", + " ## boundingRect _must_ indicate the entire area that will be drawn on\n", + " ## or else we will get artifacts and possibly crashing.\n", + " ## (in this case, QPicture does all the work of computing the bouning rect for us)\n", + " return QtCore.QRectF(self.picture.boundingRect())\n", + "\n", + "data = [ ## fields are (time, open, close, min, max).\n", + " (1., 10, 13, 5, 15),\n", + " (2., 13, 17, 9, 20),\n", + " (3., 17, 14, 11, 23),\n", + " (4., 14, 15, 5, 19),\n", + " (5., 15, 9, 8, 22),\n", + " (6., 9, 15, 8, 16),\n", + "]\n", + "item = CandlestickItem(data)\n", + "plt = pg.plot()\n", + "plt.addItem(item)\n", + "plt.setWindowTitle('pyqtgraph example: customGraphicsItem')\n", + "\n", + "## Start Qt event loop unless running in interactive mode or using pyside.\n", + "if __name__ == '__main__':\n", + " import sys\n", + " if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):\n", + " QtGui.QApplication.instance().exec_()" + ], + "outputs": [ + { + "output_type": "stream", + "name": "stderr", + "text": [ + "QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-sean'\n", + "libGL error: No matching fbConfigs or visuals found\n", + "libGL error: failed to load driver: swrast\n" + ] } ], "metadata": {} diff --git a/newqt.py b/newqt.py index 463fc26..0b2ece9 100644 --- a/newqt.py +++ b/newqt.py @@ -46,16 +46,17 @@ def __init__(self, picklepath = None, dfs = None): self.leftbar = QVBoxLayout() - if picklepath is None: - self.plotpanels,self.data = Test2Plots() - elif dfs is None: - self.dfs = getOHLC_pickle(picklepath) + if dfs is not None: + self.dfs = dfs self.data = self.dfs[0] self.plotpanels = [PlotPanel(df) for df in self.dfs] - else: - self.dfs = dfs + elif picklepath is not None: + self.dfs = getOHLC_pickle(picklepath) self.data = self.dfs[0] self.plotpanels = [PlotPanel(df) for df in self.dfs] + else: + self.plotpanels,self.data = Test2Plots() + #print(self.data.tail(100)) self.rightmain = PGFigureLayoutWrap(self.plotpanels, len(self.data)) self.layout.addLayout(self.leftbar) @@ -157,9 +158,10 @@ def Test2Plots(): return plotpanels,data -app = QApplication(sys.argv) -window = MainWindow() -window.show() -app.exec() \ No newline at end of file +if __name__ == "__main__": + app = QApplication(sys.argv) + window = MainWindow() + window.show() + app.exec() \ No newline at end of file