1#!/usr/bin/env python 2# -*- coding: utf-8; py-indent-offset:4 -*- 3############################################################################### 4# 5# Copyright (C) 2015, 2016, 2017 Daniel Rodriguez 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############################################################################### 21from __future__ import (absolute_import, division, print_function, 22 unicode_literals) 23 24 25from . import Filter 26 27 28__all__ = ['Renko'] 29 30 31class Renko(Filter): 32 '''Modify the data stream to draw Renko bars (or bricks) 33 34 Params: 35 36 - ``hilo`` (default: *False*) Use high and low instead of close to decide 37 if a new brick is needed 38 39 - ``size`` (default: *None*) The size to consider for each brick 40 41 - ``autosize`` (default: *20.0*) If *size* is *None*, this will be used 42 to autocalculate the size of the bricks (simply dividing the current 43 price by the given value) 44 45 - ``dynamic`` (default: *False*) If *True* and using *autosize*, the size 46 of the bricks will be recalculated when moving to a new brick. This 47 will of course eliminate the perfect alignment of Renko bricks. 48 49 - ``align`` (default: *1.0*) Factor use to align the price boundaries of 50 the bricks. If the price is for example *3563.25* and *align* is 51 *10.0*, the resulting aligned price will be *3560*. The calculation: 52 53 - 3563.25 / 10.0 = 356.325 54 - round it and remove the decimals -> 356 55 - 356 * 10.0 -> 3560 56 57 See: 58 - http://stockcharts.com/school/doku.php?id=chart_school:chart_analysis:renko 59 60 ''' 61 62 params = ( 63 ('hilo', False), 64 ('size', None), 65 ('autosize', 20.0), 66 ('dynamic', False), 67 ('align', 1.0), 68 ) 69 70 def nextstart(self, data): 71 o = data.open[0] 72 o = round(o / self.p.align, 0) * self.p.align # aligned 73 self._size = self.p.size or float(o // self.p.autosize) 74 self._top = int(o) + self._size 75 self._bot = int(o) - self._size 76 77 def next(self, data): 78 c = data.close[0] 79 h = data.high[0] 80 l = data.low[0] 81 82 if self.p.hilo: 83 hiprice = h 84 loprice = l 85 else: 86 hiprice = loprice = c 87 88 if hiprice >= self._top: 89 # deliver a renko brick from top -> top + size 90 self._bot = bot = self._top 91 92 if self.p.size is None and self.p.dynamic: 93 self._size = float(c // self.p.autosize) 94 top = bot + self._size 95 top = round(top / self.p.align, 0) * self.p.align # aligned 96 else: 97 top = bot + self._size 98 99 self._top = top 100 101 data.open[0] = bot 102 data.low[0] = bot 103 data.high[0] = top 104 data.close[0] = top 105 data.volume[0] = 0.0 106 data.openinterest[0] = 0.0 107 return False # length of data stream is unaltered 108 109 elif loprice <= self._bot: 110 # deliver a renko brick from bot -> bot - size 111 self._top = top = self._bot 112 113 if self.p.size is None and self.p.dynamic: 114 self._size = float(c // self.p.autosize) 115 bot = top - self._size 116 bot = round(bot / self.p.align, 0) * self.p.align # aligned 117 else: 118 bot = top - self._size 119 120 self._bot = bot 121 122 data.open[0] = top 123 data.low[0] = top 124 data.high[0] = bot 125 data.close[0] = bot 126 data.volume[0] = 0.0 127 data.openinterest[0] = 0.0 128 return False # length of data stream is unaltered 129 130 data.backwards() 131 return True # length of stream was changed, get new bar 132