Module backtrader.functions
Expand source code
#!/usr/bin/env python
# -*- coding: utf-8; py-indent-offset:4 -*-
###############################################################################
#
# Copyright (C) 2015-2023 Daniel Rodriguez
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
from __future__ import (absolute_import, division, print_function,
unicode_literals)
import functools
import math
from .linebuffer import LineActions
from .utils.py3 import cmp, range
# Generate a List equivalent which uses "is" for contains
class List(list):
def __contains__(self, other):
return any(x.__hash__() == other.__hash__() for x in self)
class Logic(LineActions):
def __init__(self, *args):
super(Logic, self).__init__()
self.args = [self.arrayize(arg) for arg in args]
class DivByZero(Logic):
'''This operation is a Lines object and fills it values by executing a
division on the numerator / denominator arguments and avoiding a division
by zero exception by checking the denominator
Params:
- a: numerator (numeric or iterable object ... mostly a Lines object)
- b: denominator (numeric or iterable object ... mostly a Lines object)
- zero (def: 0.0): value to apply if division by zero would be raised
'''
def __init__(self, a, b, zero=0.0):
super(DivByZero, self).__init__(a, b)
self.a = a
self.b = b
self.zero = zero
def next(self):
b = self.b[0]
self[0] = self.a[0] / b if b else self.zero
def once(self, start, end):
# cache python dictionary lookups
dst = self.array
srca = self.a.array
srcb = self.b.array
zero = self.zero
for i in range(start, end):
b = srcb[i]
dst[i] = srca[i] / b if b else zero
class DivZeroByZero(Logic):
'''This operation is a Lines object and fills it values by executing a
division on the numerator / denominator arguments and avoiding a division
by zero exception or an indetermination by checking the
denominator/numerator pair
Params:
- a: numerator (numeric or iterable object ... mostly a Lines object)
- b: denominator (numeric or iterable object ... mostly a Lines object)
- single (def: +inf): value to apply if division is x / 0
- dual (def: 0.0): value to apply if division is 0 / 0
'''
def __init__(self, a, b, single=float('inf'), dual=0.0):
super(DivZeroByZero, self).__init__(a, b)
self.a = a
self.b = b
self.single = single
self.dual = dual
def next(self):
b = self.b[0]
a = self.a[0]
if b == 0.0:
self[0] = self.dual if a == 0.0 else self.single
else:
self[0] = self.a[0] / b
def once(self, start, end):
# cache python dictionary lookups
dst = self.array
srca = self.a.array
srcb = self.b.array
single = self.single
dual = self.dual
for i in range(start, end):
b = srcb[i]
a = srca[i]
if b == 0.0:
dst[i] = dual if a == 0.0 else single
else:
dst[i] = a / b
class Cmp(Logic):
def __init__(self, a, b):
super(Cmp, self).__init__(a, b)
self.a = self.args[0]
self.b = self.args[1]
def next(self):
self[0] = cmp(self.a[0], self.b[0])
def once(self, start, end):
# cache python dictionary lookups
dst = self.array
srca = self.a.array
srcb = self.b.array
for i in range(start, end):
dst[i] = cmp(srca[i], srcb[i])
class CmpEx(Logic):
def __init__(self, a, b, r1, r2, r3):
super(CmpEx, self).__init__(a, b, r1, r2, r3)
self.a = self.args[0]
self.b = self.args[1]
self.r1 = self.args[2]
self.r2 = self.args[3]
self.r3 = self.args[4]
def next(self):
self[0] = cmp(self.a[0], self.b[0])
def once(self, start, end):
# cache python dictionary lookups
dst = self.array
srca = self.a.array
srcb = self.b.array
r1 = self.r1.array
r2 = self.r2.array
r3 = self.r3.array
for i in range(start, end):
ai = srca[i]
bi = srcb[i]
if ai < bi:
dst[i] = r1[i]
elif ai > bi:
dst[i] = r3[i]
else:
dst[i] = r2[i]
class If(Logic):
def __init__(self, cond, a, b):
super(If, self).__init__(a, b)
self.a = self.args[0]
self.b = self.args[1]
self.cond = self.arrayize(cond)
def next(self):
self[0] = self.a[0] if self.cond[0] else self.b[0]
def once(self, start, end):
# cache python dictionary lookups
dst = self.array
srca = self.a.array
srcb = self.b.array
cond = self.cond.array
for i in range(start, end):
dst[i] = srca[i] if cond[i] else srcb[i]
class MultiLogic(Logic):
def next(self):
self[0] = self.flogic([arg[0] for arg in self.args])
def once(self, start, end):
# cache python dictionary lookups
dst = self.array
arrays = [arg.array for arg in self.args]
flogic = self.flogic
for i in range(start, end):
dst[i] = flogic([arr[i] for arr in arrays])
class MultiLogicReduce(MultiLogic):
def __init__(self, *args, **kwargs):
super(MultiLogicReduce, self).__init__(*args)
if 'initializer' not in kwargs:
self.flogic = functools.partial(functools.reduce, self.flogic)
else:
self.flogic = functools.partial(functools.reduce, self.flogic,
initializer=kwargs['initializer'])
class Reduce(MultiLogicReduce):
def __init__(self, flogic, *args, **kwargs):
self.flogic = flogic
super(Reduce, self).__init__(*args, **kwargs)
# The _xxxlogic functions are defined at module scope to make them
# pickable and therefore compatible with multiprocessing
def _andlogic(x, y):
return bool(x and y)
class And(MultiLogicReduce):
flogic = staticmethod(_andlogic)
def _orlogic(x, y):
return bool(x or y)
class Or(MultiLogicReduce):
flogic = staticmethod(_orlogic)
class Max(MultiLogic):
flogic = max
class Min(MultiLogic):
flogic = min
class Sum(MultiLogic):
flogic = math.fsum
class Any(MultiLogic):
flogic = any
class All(MultiLogic):
flogic = all
Classes
class All (*args)
-
Base class derived from LineBuffer intented to defined the minimum interface to make it compatible with a LineIterator by providing operational _next and _once interfaces.
The metaclass does the dirty job of calculating minperiods and registering
Expand source code
class All(MultiLogic): flogic = all
Ancestors
Class variables
var frompackages
var packages
var params
Methods
def flogic(iterable, /)
-
Return True if bool(x) is True for all values x in the iterable.
If the iterable is empty, return True.
Inherited members
MultiLogic
:addbinding
addminperiod
advance
backwards
bind2line
bind2lines
buflen
dt
extend
forward
get
getzero
getzeroval
home
incminperiod
minbuffer
next
nextstart
once
oncebinding
oncestart
plot
prenext
preonce
qbuffer
reset
set
setminperiod
tm
tm2datetime
tm2dtime
tm_eq
tm_ge
tm_gt
tm_le
tm_lt
tm_raw
updateminperiod
class And (*args, **kwargs)
-
Base class derived from LineBuffer intented to defined the minimum interface to make it compatible with a LineIterator by providing operational _next and _once interfaces.
The metaclass does the dirty job of calculating minperiods and registering
Expand source code
class And(MultiLogicReduce): flogic = staticmethod(_andlogic)
Ancestors
Class variables
var frompackages
var packages
var params
Static methods
def flogic(x, y)
-
Expand source code
def _andlogic(x, y): return bool(x and y)
Inherited members
MultiLogicReduce
:addbinding
addminperiod
advance
backwards
bind2line
bind2lines
buflen
dt
extend
forward
get
getzero
getzeroval
home
incminperiod
minbuffer
next
nextstart
once
oncebinding
oncestart
plot
prenext
preonce
qbuffer
reset
set
setminperiod
tm
tm2datetime
tm2dtime
tm_eq
tm_ge
tm_gt
tm_le
tm_lt
tm_raw
updateminperiod
class Any (*args)
-
Base class derived from LineBuffer intented to defined the minimum interface to make it compatible with a LineIterator by providing operational _next and _once interfaces.
The metaclass does the dirty job of calculating minperiods and registering
Expand source code
class Any(MultiLogic): flogic = any
Ancestors
Class variables
var frompackages
var packages
var params
Methods
def flogic(iterable, /)
-
Return True if bool(x) is True for any x in the iterable.
If the iterable is empty, return False.
Inherited members
MultiLogic
:addbinding
addminperiod
advance
backwards
bind2line
bind2lines
buflen
dt
extend
forward
get
getzero
getzeroval
home
incminperiod
minbuffer
next
nextstart
once
oncebinding
oncestart
plot
prenext
preonce
qbuffer
reset
set
setminperiod
tm
tm2datetime
tm2dtime
tm_eq
tm_ge
tm_gt
tm_le
tm_lt
tm_raw
updateminperiod
class Cmp (a, b)
-
Base class derived from LineBuffer intented to defined the minimum interface to make it compatible with a LineIterator by providing operational _next and _once interfaces.
The metaclass does the dirty job of calculating minperiods and registering
Expand source code
class Cmp(Logic): def __init__(self, a, b): super(Cmp, self).__init__(a, b) self.a = self.args[0] self.b = self.args[1] def next(self): self[0] = cmp(self.a[0], self.b[0]) def once(self, start, end): # cache python dictionary lookups dst = self.array srca = self.a.array srcb = self.b.array for i in range(start, end): dst[i] = cmp(srca[i], srcb[i])
Ancestors
Class variables
var frompackages
var packages
var params
Inherited members
Logic
:addbinding
addminperiod
advance
backwards
bind2line
bind2lines
buflen
dt
extend
forward
get
getzero
getzeroval
home
incminperiod
minbuffer
next
nextstart
once
oncebinding
oncestart
plot
prenext
preonce
qbuffer
reset
set
setminperiod
tm
tm2datetime
tm2dtime
tm_eq
tm_ge
tm_gt
tm_le
tm_lt
tm_raw
updateminperiod
class CmpEx (a, b, r1, r2, r3)
-
Base class derived from LineBuffer intented to defined the minimum interface to make it compatible with a LineIterator by providing operational _next and _once interfaces.
The metaclass does the dirty job of calculating minperiods and registering
Expand source code
class CmpEx(Logic): def __init__(self, a, b, r1, r2, r3): super(CmpEx, self).__init__(a, b, r1, r2, r3) self.a = self.args[0] self.b = self.args[1] self.r1 = self.args[2] self.r2 = self.args[3] self.r3 = self.args[4] def next(self): self[0] = cmp(self.a[0], self.b[0]) def once(self, start, end): # cache python dictionary lookups dst = self.array srca = self.a.array srcb = self.b.array r1 = self.r1.array r2 = self.r2.array r3 = self.r3.array for i in range(start, end): ai = srca[i] bi = srcb[i] if ai < bi: dst[i] = r1[i] elif ai > bi: dst[i] = r3[i] else: dst[i] = r2[i]
Ancestors
Class variables
var frompackages
var packages
var params
Inherited members
Logic
:addbinding
addminperiod
advance
backwards
bind2line
bind2lines
buflen
dt
extend
forward
get
getzero
getzeroval
home
incminperiod
minbuffer
next
nextstart
once
oncebinding
oncestart
plot
prenext
preonce
qbuffer
reset
set
setminperiod
tm
tm2datetime
tm2dtime
tm_eq
tm_ge
tm_gt
tm_le
tm_lt
tm_raw
updateminperiod
class DivByZero (a, b, zero=0.0)
-
This operation is a Lines object and fills it values by executing a division on the numerator / denominator arguments and avoiding a division by zero exception by checking the denominator
Params
- a: numerator (numeric or iterable object … mostly a Lines object)
- b: denominator (numeric or iterable object … mostly a Lines object)
- zero (def: 0.0): value to apply if division by zero would be raised
Expand source code
class DivByZero(Logic): '''This operation is a Lines object and fills it values by executing a division on the numerator / denominator arguments and avoiding a division by zero exception by checking the denominator Params: - a: numerator (numeric or iterable object ... mostly a Lines object) - b: denominator (numeric or iterable object ... mostly a Lines object) - zero (def: 0.0): value to apply if division by zero would be raised ''' def __init__(self, a, b, zero=0.0): super(DivByZero, self).__init__(a, b) self.a = a self.b = b self.zero = zero def next(self): b = self.b[0] self[0] = self.a[0] / b if b else self.zero def once(self, start, end): # cache python dictionary lookups dst = self.array srca = self.a.array srcb = self.b.array zero = self.zero for i in range(start, end): b = srcb[i] dst[i] = srca[i] / b if b else zero
Ancestors
Class variables
var frompackages
var packages
var params
Inherited members
Logic
:addbinding
addminperiod
advance
backwards
bind2line
bind2lines
buflen
dt
extend
forward
get
getzero
getzeroval
home
incminperiod
minbuffer
next
nextstart
once
oncebinding
oncestart
plot
prenext
preonce
qbuffer
reset
set
setminperiod
tm
tm2datetime
tm2dtime
tm_eq
tm_ge
tm_gt
tm_le
tm_lt
tm_raw
updateminperiod
class DivZeroByZero (a, b, single=inf, dual=0.0)
-
This operation is a Lines object and fills it values by executing a division on the numerator / denominator arguments and avoiding a division by zero exception or an indetermination by checking the denominator/numerator pair
Params
- a: numerator (numeric or iterable object … mostly a Lines object)
- b: denominator (numeric or iterable object … mostly a Lines object)
- single (def: +inf): value to apply if division is x / 0
- dual (def: 0.0): value to apply if division is 0 / 0
Expand source code
class DivZeroByZero(Logic): '''This operation is a Lines object and fills it values by executing a division on the numerator / denominator arguments and avoiding a division by zero exception or an indetermination by checking the denominator/numerator pair Params: - a: numerator (numeric or iterable object ... mostly a Lines object) - b: denominator (numeric or iterable object ... mostly a Lines object) - single (def: +inf): value to apply if division is x / 0 - dual (def: 0.0): value to apply if division is 0 / 0 ''' def __init__(self, a, b, single=float('inf'), dual=0.0): super(DivZeroByZero, self).__init__(a, b) self.a = a self.b = b self.single = single self.dual = dual def next(self): b = self.b[0] a = self.a[0] if b == 0.0: self[0] = self.dual if a == 0.0 else self.single else: self[0] = self.a[0] / b def once(self, start, end): # cache python dictionary lookups dst = self.array srca = self.a.array srcb = self.b.array single = self.single dual = self.dual for i in range(start, end): b = srcb[i] a = srca[i] if b == 0.0: dst[i] = dual if a == 0.0 else single else: dst[i] = a / b
Ancestors
Class variables
var frompackages
var packages
var params
Inherited members
Logic
:addbinding
addminperiod
advance
backwards
bind2line
bind2lines
buflen
dt
extend
forward
get
getzero
getzeroval
home
incminperiod
minbuffer
next
nextstart
once
oncebinding
oncestart
plot
prenext
preonce
qbuffer
reset
set
setminperiod
tm
tm2datetime
tm2dtime
tm_eq
tm_ge
tm_gt
tm_le
tm_lt
tm_raw
updateminperiod
class If (cond, a, b)
-
Base class derived from LineBuffer intented to defined the minimum interface to make it compatible with a LineIterator by providing operational _next and _once interfaces.
The metaclass does the dirty job of calculating minperiods and registering
Expand source code
class If(Logic): def __init__(self, cond, a, b): super(If, self).__init__(a, b) self.a = self.args[0] self.b = self.args[1] self.cond = self.arrayize(cond) def next(self): self[0] = self.a[0] if self.cond[0] else self.b[0] def once(self, start, end): # cache python dictionary lookups dst = self.array srca = self.a.array srcb = self.b.array cond = self.cond.array for i in range(start, end): dst[i] = srca[i] if cond[i] else srcb[i]
Ancestors
Class variables
var frompackages
var packages
var params
Inherited members
Logic
:addbinding
addminperiod
advance
backwards
bind2line
bind2lines
buflen
dt
extend
forward
get
getzero
getzeroval
home
incminperiod
minbuffer
next
nextstart
once
oncebinding
oncestart
plot
prenext
preonce
qbuffer
reset
set
setminperiod
tm
tm2datetime
tm2dtime
tm_eq
tm_ge
tm_gt
tm_le
tm_lt
tm_raw
updateminperiod
class List (*args, **kwargs)
-
Built-in mutable sequence.
If no argument is given, the constructor creates a new empty list. The argument must be an iterable if specified.
Expand source code
class List(list): def __contains__(self, other): return any(x.__hash__() == other.__hash__() for x in self)
Ancestors
- builtins.list
class Logic (*args)
-
Base class derived from LineBuffer intented to defined the minimum interface to make it compatible with a LineIterator by providing operational _next and _once interfaces.
The metaclass does the dirty job of calculating minperiods and registering
Expand source code
class Logic(LineActions): def __init__(self, *args): super(Logic, self).__init__() self.args = [self.arrayize(arg) for arg in args]
Ancestors
Subclasses
Class variables
var frompackages
var packages
var params
Inherited members
LineActions
:addbinding
addminperiod
advance
backwards
bind2line
bind2lines
buflen
dt
extend
forward
get
getzero
getzeroval
home
incminperiod
minbuffer
next
nextstart
once
oncebinding
oncestart
plot
prenext
preonce
qbuffer
reset
set
setminperiod
tm
tm2datetime
tm2dtime
tm_eq
tm_ge
tm_gt
tm_le
tm_lt
tm_raw
updateminperiod
class Max (*args)
-
Base class derived from LineBuffer intented to defined the minimum interface to make it compatible with a LineIterator by providing operational _next and _once interfaces.
The metaclass does the dirty job of calculating minperiods and registering
Expand source code
class Max(MultiLogic): flogic = max
Ancestors
Class variables
var frompackages
var packages
var params
Methods
def flogic(...)
-
max(iterable, [, default=obj, key=func]) -> value max(arg1, arg2, args, *[, key=func]) -> value
With a single iterable argument, return its biggest item. The default keyword-only argument specifies an object to return if the provided iterable is empty. With two or more arguments, return the largest argument.
Inherited members
MultiLogic
:addbinding
addminperiod
advance
backwards
bind2line
bind2lines
buflen
dt
extend
forward
get
getzero
getzeroval
home
incminperiod
minbuffer
next
nextstart
once
oncebinding
oncestart
plot
prenext
preonce
qbuffer
reset
set
setminperiod
tm
tm2datetime
tm2dtime
tm_eq
tm_ge
tm_gt
tm_le
tm_lt
tm_raw
updateminperiod
class Min (*args)
-
Base class derived from LineBuffer intented to defined the minimum interface to make it compatible with a LineIterator by providing operational _next and _once interfaces.
The metaclass does the dirty job of calculating minperiods and registering
Expand source code
class Min(MultiLogic): flogic = min
Ancestors
Class variables
var frompackages
var packages
var params
Methods
def flogic(...)
-
min(iterable, [, default=obj, key=func]) -> value min(arg1, arg2, args, *[, key=func]) -> value
With a single iterable argument, return its smallest item. The default keyword-only argument specifies an object to return if the provided iterable is empty. With two or more arguments, return the smallest argument.
Inherited members
MultiLogic
:addbinding
addminperiod
advance
backwards
bind2line
bind2lines
buflen
dt
extend
forward
get
getzero
getzeroval
home
incminperiod
minbuffer
next
nextstart
once
oncebinding
oncestart
plot
prenext
preonce
qbuffer
reset
set
setminperiod
tm
tm2datetime
tm2dtime
tm_eq
tm_ge
tm_gt
tm_le
tm_lt
tm_raw
updateminperiod
class MultiLogic (*args)
-
Base class derived from LineBuffer intented to defined the minimum interface to make it compatible with a LineIterator by providing operational _next and _once interfaces.
The metaclass does the dirty job of calculating minperiods and registering
Expand source code
class MultiLogic(Logic): def next(self): self[0] = self.flogic([arg[0] for arg in self.args]) def once(self, start, end): # cache python dictionary lookups dst = self.array arrays = [arg.array for arg in self.args] flogic = self.flogic for i in range(start, end): dst[i] = flogic([arr[i] for arr in arrays])
Ancestors
Subclasses
Class variables
var frompackages
var packages
var params
Inherited members
Logic
:addbinding
addminperiod
advance
backwards
bind2line
bind2lines
buflen
dt
extend
forward
get
getzero
getzeroval
home
incminperiod
minbuffer
next
nextstart
once
oncebinding
oncestart
plot
prenext
preonce
qbuffer
reset
set
setminperiod
tm
tm2datetime
tm2dtime
tm_eq
tm_ge
tm_gt
tm_le
tm_lt
tm_raw
updateminperiod
class MultiLogicReduce (*args, **kwargs)
-
Base class derived from LineBuffer intented to defined the minimum interface to make it compatible with a LineIterator by providing operational _next and _once interfaces.
The metaclass does the dirty job of calculating minperiods and registering
Expand source code
class MultiLogicReduce(MultiLogic): def __init__(self, *args, **kwargs): super(MultiLogicReduce, self).__init__(*args) if 'initializer' not in kwargs: self.flogic = functools.partial(functools.reduce, self.flogic) else: self.flogic = functools.partial(functools.reduce, self.flogic, initializer=kwargs['initializer'])
Ancestors
Subclasses
Class variables
var frompackages
var packages
var params
Inherited members
MultiLogic
:addbinding
addminperiod
advance
backwards
bind2line
bind2lines
buflen
dt
extend
forward
get
getzero
getzeroval
home
incminperiod
minbuffer
next
nextstart
once
oncebinding
oncestart
plot
prenext
preonce
qbuffer
reset
set
setminperiod
tm
tm2datetime
tm2dtime
tm_eq
tm_ge
tm_gt
tm_le
tm_lt
tm_raw
updateminperiod
class Or (*args, **kwargs)
-
Base class derived from LineBuffer intented to defined the minimum interface to make it compatible with a LineIterator by providing operational _next and _once interfaces.
The metaclass does the dirty job of calculating minperiods and registering
Expand source code
class Or(MultiLogicReduce): flogic = staticmethod(_orlogic)
Ancestors
Class variables
var frompackages
var packages
var params
Static methods
def flogic(x, y)
-
Expand source code
def _orlogic(x, y): return bool(x or y)
Inherited members
MultiLogicReduce
:addbinding
addminperiod
advance
backwards
bind2line
bind2lines
buflen
dt
extend
forward
get
getzero
getzeroval
home
incminperiod
minbuffer
next
nextstart
once
oncebinding
oncestart
plot
prenext
preonce
qbuffer
reset
set
setminperiod
tm
tm2datetime
tm2dtime
tm_eq
tm_ge
tm_gt
tm_le
tm_lt
tm_raw
updateminperiod
class Reduce (flogic, *args, **kwargs)
-
Base class derived from LineBuffer intented to defined the minimum interface to make it compatible with a LineIterator by providing operational _next and _once interfaces.
The metaclass does the dirty job of calculating minperiods and registering
Expand source code
class Reduce(MultiLogicReduce): def __init__(self, flogic, *args, **kwargs): self.flogic = flogic super(Reduce, self).__init__(*args, **kwargs)
Ancestors
Class variables
var frompackages
var packages
var params
Inherited members
MultiLogicReduce
:addbinding
addminperiod
advance
backwards
bind2line
bind2lines
buflen
dt
extend
forward
get
getzero
getzeroval
home
incminperiod
minbuffer
next
nextstart
once
oncebinding
oncestart
plot
prenext
preonce
qbuffer
reset
set
setminperiod
tm
tm2datetime
tm2dtime
tm_eq
tm_ge
tm_gt
tm_le
tm_lt
tm_raw
updateminperiod
class Sum (*args)
-
Base class derived from LineBuffer intented to defined the minimum interface to make it compatible with a LineIterator by providing operational _next and _once interfaces.
The metaclass does the dirty job of calculating minperiods and registering
Expand source code
class Sum(MultiLogic): flogic = math.fsum
Ancestors
Class variables
var frompackages
var packages
var params
Methods
def flogic(seq, /)
-
Return an accurate floating point sum of values in the iterable seq.
Assumes IEEE-754 floating point arithmetic.
Inherited members
MultiLogic
:addbinding
addminperiod
advance
backwards
bind2line
bind2lines
buflen
dt
extend
forward
get
getzero
getzeroval
home
incminperiod
minbuffer
next
nextstart
once
oncebinding
oncestart
plot
prenext
preonce
qbuffer
reset
set
setminperiod
tm
tm2datetime
tm2dtime
tm_eq
tm_ge
tm_gt
tm_le
tm_lt
tm_raw
updateminperiod