Skip to content

Commit 8a730b5

Browse files
committed
Ichimoku is now OK
1 parent 0ecaf5b commit 8a730b5

File tree

6 files changed

+163
-11
lines changed

6 files changed

+163
-11
lines changed

Controller.py

+9-5
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ def loadData(self, dataPath):
8181
self.data = bt.feeds.PandasData(dataname=self.dataframe, timeframe=bt.TimeFrame.Minutes)
8282

8383
self.cerebro.adddata(self.data) # Add the data feed
84+
85+
# Draw charts based on input data
86+
self.interface.drawFinPlots(self.dataframe)
87+
8488
pass
8589

8690
def addStrategy(self, strategyName):
@@ -94,22 +98,23 @@ def addStrategy(self, strategyName):
9498
pass
9599

96100
def run(self):
101+
102+
# Compute strategy results
97103
results = self.cerebro.run() # run it all
98104
self.strat_results = results[0] # results of the first strategy
99105

100-
self.generateStats()
106+
# Display results
107+
self.displayStrategyResults()
101108
pass
102109

103-
def generateStats(self):
110+
def displayStrategyResults(self):
104111
# Stats on trades
105112
#portfolio_stats = self.strat_results.analyzers.getbyname('PyFolio')
106113
#self.returns, self.positions, self.transactions, self.gross_lev = portfolio_stats.get_pf_items()
107114
#self.portfolio_transactions = self.strat_results.analyzers.Transactions.get_analysis().items()
108115
#self.returns.index = self.returns.index.tz_convert(None)
109116

110117
#self.interface.createTransactionsUI(self.portfolio_transactions)
111-
112-
self.interface.drawFinPlots(self.dataframe)
113118
self.interface.fillSummaryUI(self.strat_results.stats.broker.cash[0], self.strat_results.stats.broker.value[0], self.strat_results.analyzers.ta.get_analysis())
114119
self.interface.fillTradesUI(self.strat_results._trades.items())
115120

@@ -126,7 +131,6 @@ def generateStats(self):
126131

127132
pass
128133

129-
130134
def displayUI(self):
131135

132136
self.interface.show()

images/gitkeep.txt

Whitespace-only changes.

indicators/__init__.py

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8; py-indent-offset:4 -*-
3+
###############################################################################
4+
#
5+
# Copyright (C) 2021-2025 Skinok
6+
#
7+
# This program is free software: you can redistribute it and/or modify
8+
# it under the terms of the GNU General Public License as published by
9+
# the Free Software Foundation, either version 3 of the License, or
10+
# (at your option) any later version.
11+
#
12+
# This program is distributed in the hope that it will be useful,
13+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
# GNU General Public License for more details.
16+
#
17+
# You should have received a copy of the GNU General Public License
18+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
#
20+
###############################################################################
21+

indicators/fin_macd.py

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#!/usr/bin/env python3
2+
3+
import finplot as fplt
4+
5+
import backtrader as bt
6+
import backtrader.indicators as btind
7+
8+
class Macd():
9+
10+
'''
11+
dataFrames should be : ['Date','Open','Close']
12+
ax is the finplot plot previously created
13+
'''
14+
def __init__(self, dataFrames, ax):
15+
16+
self.macd_ax = fplt.create_plot('MACD', rows=2)
17+
18+
# plot macd with standard colors first
19+
self.macd = dataFrames.Close.ewm(span=12).mean() - dataFrames.Close.ewm(span=26).mean()
20+
self.signal = self.macd.ewm(span=9).mean()
21+
22+
#self.macd = bt.indicators.MACD(dataFrames, period_me1 = )
23+
24+
# Add MACD Diff to the data frames
25+
dataFrames['macd_diff'] = self.macd - self.signal
26+
27+
# draw MACD in the MACD window (self.macd_ax)
28+
fplt.volume_ocv(dataFrames[['TimeInt','Open','Close','macd_diff']], ax=ax, colorfunc=fplt.strength_colorfilter)
29+
fplt.plot(self.macd, ax=ax, legend='MACD')
30+
fplt.plot(self.signal, ax=ax, legend='Signal')
31+
pass

indicators/ichimoku.py

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#!/usr/bin/env python3
2+
3+
import sys
4+
5+
from pyqtgraph.functions import Color
6+
sys.path.append('../finplot')
7+
import finplot as fplt
8+
9+
import backtrader as bt
10+
import backtrader.indicators as btind
11+
12+
import pandas as pd
13+
14+
class Ichimoku():
15+
16+
'''
17+
Developed and published in his book in 1969 by journalist Goichi Hosoda
18+
19+
Formula:
20+
- tenkan_sen = (Highest(High, tenkan) + Lowest(Low, tenkan)) / 2.0
21+
- kijun_sen = (Highest(High, kijun) + Lowest(Low, kijun)) / 2.0
22+
23+
The next 2 are pushed 26 bars into the future
24+
25+
- senkou_span_a = (tenkan_sen + kijun_sen) / 2.0
26+
- senkou_span_b = ((Highest(High, senkou) + Lowest(Low, senkou)) / 2.0
27+
28+
This is pushed 26 bars into the past
29+
30+
- chikou = close
31+
32+
The cloud (Kumo) is formed by the area between the senkou_spans
33+
34+
See:
35+
- http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:ichimoku_cloud
36+
37+
'''
38+
39+
def __init__(self, dataFrames, tenkan = 9, kijun = 26, senkou = 52, senkou_lead = 26, chikou = 26):
40+
41+
# Tenkan-sen (Conversion Line): (9-period high + 9-period low)/2))
42+
period9_high = dataFrames['High'].rolling(window=tenkan).max()
43+
period9_low = dataFrames['Low'].rolling(window=tenkan).min()
44+
self.tenkan_sen = (period9_high + period9_low) / 2
45+
46+
# Kijun-sen (Base Line): (26-period high + 26-period low)/2))
47+
period26_high = dataFrames['High'].rolling(window=kijun).max()
48+
period26_low = dataFrames['Low'].rolling(window=kijun).min()
49+
self.kijun_sen = (period26_high + period26_low) / 2
50+
51+
# Senkou Span A (Leading Span A): (Conversion Line + Base Line)/2))
52+
self.senkou_span_a = ((self.tenkan_sen + self.kijun_sen) / 2).shift(senkou_lead)
53+
54+
# Senkou Span B (Leading Span B): (52-period high + 52-period low)/2))
55+
period52_high = dataFrames['High'].rolling(window=senkou).max()
56+
period52_low = dataFrames['Low'].rolling(window=senkou).min()
57+
self.senkou_span_b = ((period52_high + period52_low) / 2).shift(senkou_lead)
58+
59+
# The most current closing price plotted 26 time periods behind (optional)
60+
self.chikou_span = dataFrames['Close'].shift(-chikou) # 26 according to investopedia
61+
62+
pass
63+
64+
def draw(self, ax, tenkan_color = "magenta", kijun_color = "blue", senkou_a_color = "gray", senkou_b_color = "gray", chikou_color = "yellow"):
65+
66+
self.tenkan_sen_plot = fplt.plot(self.tenkan_sen, ax = ax, color=tenkan_color, width=2 )
67+
self.kijun_sen_plot = fplt.plot(self.kijun_sen, ax = ax, color=kijun_color, width=3 )
68+
self.senkou_span_a_plot = fplt.plot(self.senkou_span_a, ax = ax, color=senkou_a_color )
69+
self.senkou_span_b_plot = fplt.plot(self.senkou_span_b, ax = ax, color=senkou_b_color )
70+
self.chikou_span_plot = fplt.plot(self.chikou_span, ax = ax, color=chikou_color, width=3 )
71+
72+
fplt.fill_between( self.senkou_span_a_plot, self.senkou_span_b_plot, color = Color("darkGray") )
73+
74+
pass

userInterface.py

+28-6
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,14 @@
2222
from pyqtgraph.dockarea import DockArea, Dock
2323

2424
import sys
25-
sys.path.append('C:/perso/trading/anaconda3/finplot')
25+
from backtrader import indicator
26+
27+
sys.path.append('../finplot')
2628
import finplot as fplt
2729

30+
from indicators import fin_macd
31+
from indicators import ichimoku
32+
2833
import backtrader as bt
2934
import strategyTesterUI
3035

@@ -94,8 +99,6 @@ def createUIs(self):
9499

95100
pass
96101

97-
98-
99102
#########
100103
#
101104
#########
@@ -282,8 +285,8 @@ def drawFinPlots(self, data):
282285
self.data = data
283286

284287
# fin plot
285-
self.ax0, self.ax1 = fplt.create_plot_widget(master=self.area, rows=2, init_zoom_periods=100)
286-
self.area.axs = [self.ax0, self.ax1]
288+
self.ax0, self.ax1, self.ax2, self.ax3 = fplt.create_plot_widget(master=self.area, rows=4, init_zoom_periods=100)
289+
self.area.axs = [self.ax0, self.ax1, self.ax2, self.ax3]
287290
self.dock_chart.addWidget(self.ax0.ax_widget, 1, 0, 1, 2)
288291

289292
fplt.candlestick_ochl(data['Open Close High Low'.split()], ax=self.ax0)
@@ -293,6 +296,9 @@ def drawFinPlots(self, data):
293296
fplt.set_time_inspector(self.update_legend_text, ax=self.ax0, when='hover', data=data)
294297
#fplt.add_crosshair_info(self.update_crosshair_text, ax=self.ax0)
295298

299+
# Should be on a button click
300+
self.addIndicator()
301+
296302
pass
297303

298304
#########
@@ -407,7 +413,6 @@ def drawOrders(self, orders):
407413

408414
pass
409415

410-
411416
#########
412417
# Show all
413418
#########
@@ -462,6 +467,23 @@ def createTransactionsUI(self, trades):
462467

463468
pass
464469

470+
#############
471+
# Indicators
472+
#############
473+
def addIndicator(self):
474+
475+
#it should be dynamic
476+
#self.dock_indicator = Dock("dock_indi", size = (1000, 500), closable = False, hideTitle=True, )
477+
#self.area.addDock(self.dock_indicator, position='below', relativeTo=self.dock_chart)
478+
479+
#self.dock_chart.addWidget(self.ax1.ax_widget, 2, 0, 1, 2)
480+
#self.dock_indicator.addWidget(self.ax1.ax_widget, 1, 0, 1, 2)
481+
482+
ichimoku_indicator = ichimoku.Ichimoku(self.data)
483+
ichimoku_indicator.draw(self.ax0)
484+
485+
pass
486+
465487

466488

467489

0 commit comments

Comments
 (0)