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 24from . import Indicator, And 25 26 27class NonZeroDifference(Indicator): 28 ''' 29 Keeps track of the difference between two data inputs skipping, memorizing 30 the last non zero value if the current difference is zero 31 32 Formula: 33 - diff = data - data1 34 - nzd = diff if diff else diff(-1) 35 ''' 36 _mindatas = 2 # requires two (2) data sources 37 alias = ('NZD',) 38 lines = ('nzd',) 39 40 def nextstart(self): 41 self.l.nzd[0] = self.data0[0] - self.data1[0] # seed value 42 43 def next(self): 44 d = self.data0[0] - self.data1[0] 45 self.l.nzd[0] = d if d else self.l.nzd[-1] 46 47 def oncestart(self, start, end): 48 self.line.array[start] = ( 49 self.data0.array[start] - self.data1.array[start]) 50 51 def once(self, start, end): 52 d0array = self.data0.array 53 d1array = self.data1.array 54 larray = self.line.array 55 56 prev = larray[start - 1] 57 for i in range(start, end): 58 d = d0array[i] - d1array[i] 59 larray[i] = prev = d if d else prev 60 61 62class _CrossBase(Indicator): 63 _mindatas = 2 64 65 lines = ('cross',) 66 67 plotinfo = dict(plotymargin=0.05, plotyhlines=[0.0, 1.0]) 68 69 def __init__(self): 70 nzd = NonZeroDifference(self.data0, self.data1) 71 72 if self._crossup: 73 before = nzd(-1) < 0.0 # data0 was below or at 0 74 after = self.data0 > self.data1 75 else: 76 before = nzd(-1) > 0.0 # data0 was above or at 0 77 after = self.data0 < self.data1 78 79 self.lines.cross = And(before, after) 80 81 82class CrossUp(_CrossBase): 83 ''' 84 This indicator gives a signal if the 1st provided data crosses over the 2nd 85 indicator upwards 86 87 It does need to look into the current time index (0) and the previous time 88 index (-1) of both the 1st and 2nd data 89 90 Formula: 91 - diff = data - data1 92 - upcross = last_non_zero_diff < 0 and data0(0) > data1(0) 93 ''' 94 _crossup = True 95 96 97class CrossDown(_CrossBase): 98 ''' 99 This indicator gives a signal if the 1st provided data crosses over the 2nd 100 indicator upwards 101 102 It does need to look into the current time index (0) and the previous time 103 index (-1) of both the 1st and 2nd data 104 105 Formula: 106 - diff = data - data1 107 - downcross = last_non_zero_diff > 0 and data0(0) < data1(0) 108 ''' 109 _crossup = False 110 111 112class CrossOver(Indicator): 113 ''' 114 This indicator gives a signal if the provided datas (2) cross up or down. 115 116 - 1.0 if the 1st data crosses the 2nd data upwards 117 - -1.0 if the 1st data crosses the 2nd data downwards 118 119 It does need to look into the current time index (0) and the previous time 120 index (-1) of both the 1t and 2nd data 121 122 Formula: 123 - diff = data - data1 124 - upcross = last_non_zero_diff < 0 and data0(0) > data1(0) 125 - downcross = last_non_zero_diff > 0 and data0(0) < data1(0) 126 - crossover = upcross - downcross 127 ''' 128 _mindatas = 2 129 130 lines = ('crossover',) 131 132 plotinfo = dict(plotymargin=0.05, plotyhlines=[-1.0, 1.0]) 133 134 def __init__(self): 135 upcross = CrossUp(self.data, self.data1) 136 downcross = CrossDown(self.data, self.data1) 137 138 self.lines.crossover = upcross - downcross 139