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 24import math 25 26from ..observer import Observer 27 28 29class BuySell(Observer): 30 ''' 31 This observer keeps track of the individual buy/sell orders (individual 32 executions) and will plot them on the chart along the data around the 33 execution price level 34 35 Params: 36 - ``barplot`` (default: ``False``) Plot buy signals below the minimum and 37 sell signals above the maximum. 38 39 If ``False`` it will plot on the average price of executions during a 40 bar 41 42 - ``bardist`` (default: ``0.015`` 1.5%) Distance to max/min when 43 ``barplot`` is ``True`` 44 ''' 45 lines = ('buy', 'sell',) 46 47 plotinfo = dict(plot=True, subplot=False, plotlinelabels=True) 48 plotlines = dict( 49 buy=dict(marker='^', markersize=8.0, color='lime', 50 fillstyle='full', ls=''), 51 sell=dict(marker='v', markersize=8.0, color='red', 52 fillstyle='full', ls='') 53 ) 54 55 params = ( 56 ('barplot', False), # plot above/below max/min for clarity in bar plot 57 ('bardist', 0.015), # distance to max/min in absolute perc 58 ) 59 60 def next(self): 61 buy = list() 62 sell = list() 63 64 for order in self._owner._orderspending: 65 if order.data is not self.data or not order.executed.size: 66 continue 67 68 if order.isbuy(): 69 buy.append(order.executed.price) 70 else: 71 sell.append(order.executed.price) 72 73 # Take into account replay ... something could already be in there 74 # Write down the average buy/sell price 75 76 # BUY 77 curbuy = self.lines.buy[0] 78 if curbuy != curbuy: # NaN 79 curbuy = 0.0 80 self.curbuylen = curbuylen = 0 81 else: 82 curbuylen = self.curbuylen 83 84 buyops = (curbuy + math.fsum(buy)) 85 buylen = curbuylen + len(buy) 86 87 value = buyops / float(buylen or 'NaN') 88 if not self.p.barplot: 89 self.lines.buy[0] = value 90 elif value == value: # Not NaN 91 pbuy = self.data.low[0] * (1 - self.p.bardist) 92 self.lines.buy[0] = pbuy 93 94 # Update buylen values 95 curbuy = buyops 96 self.curbuylen = buylen 97 98 # SELL 99 cursell = self.lines.sell[0] 100 if cursell != cursell: # NaN 101 cursell = 0.0 102 self.curselllen = curselllen = 0 103 else: 104 curselllen = self.curselllen 105 106 sellops = (cursell + math.fsum(sell)) 107 selllen = curselllen + len(sell) 108 109 value = sellops / float(selllen or 'NaN') 110 if not self.p.barplot: 111 self.lines.sell[0] = value 112 elif value == value: # Not NaN 113 psell = self.data.high[0] * (1 + self.p.bardist) 114 self.lines.sell[0] = psell 115 116 # Update selllen values 117 cursell = sellops 118 self.curselllen = selllen 119