Skip to content

Commit

Permalink
plan to add OHLC candlestick
Browse files Browse the repository at this point in the history
  • Loading branch information
sluofoss committed Jan 19, 2022
1 parent 5f4cc39 commit 2767418
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 188 deletions.
2 changes: 1 addition & 1 deletion QTVisual/Plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
321 changes: 144 additions & 177 deletions indicatorplayground.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -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 (<anonymous>)",
"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"
]
Expand All @@ -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": {}
Expand Down
Loading

0 comments on commit 2767418

Please sign in to comment.