BUG: Reset position price (etc.) after closing position

Fixes https://github.com/kernc/backtesting.py/issues/27
This commit is contained in:
Kernc
2019-11-22 03:41:59 +01:00
parent b3cfaff295
commit 95a3519d48
3 changed files with 48 additions and 2 deletions

View File

@@ -5,6 +5,13 @@ import numpy as np
import pandas as pd
def try_(lazy_func, default=None, exception=Exception):
try:
return lazy_func()
except exception:
return default
def _as_str(value):
if isinstance(value, (Number, str)):
return str(value)

View File

@@ -406,7 +406,7 @@ class Position:
Profit (positive) or loss (negative) of current position,
in percent of position open price.
"""
return self.pl / (self.open_price * abs(self.size))
return self.pl / (self.open_price * abs(self.size) or 1)
@property
def is_long(self):
@@ -514,6 +514,8 @@ class _Broker:
self._cash += pl
self._position = 0
self._position_open_price = 0
self._position_open_i = None
@property
def equity(self):

View File

@@ -25,7 +25,9 @@ from backtesting.lib import (
plot_heatmaps
)
from backtesting.test import GOOG, EURUSD, SMA
from backtesting._util import _Indicator, _as_str, _Array
from backtesting._util import _Indicator, _as_str, _Array, try_
SHORT_DATA = GOOG.iloc[:20] # Short data for fast tests with no indicator lag
@contextmanager
@@ -297,6 +299,41 @@ class TestBacktest(TestCase):
self.assertEqual(stats['_strategy'].__class__, strategy)
class TestStrategy(TestCase):
def test_position(self):
def coroutine(self):
yield self.buy()
assert self.position
assert self.position.is_long
assert not self.position.is_short
assert self.position.size > 0
assert self.position.pl
assert self.position.pl_pct
assert self.position.open_price > 0
assert self.position.open_time
yield self.position.close()
assert not self.position
assert not self.position.is_long
assert not self.position.is_short
assert not self.position.size
assert not self.position.pl
assert not self.position.pl_pct
assert not self.position.open_price
assert not self.position.open_time
class S(Strategy):
def init(self):
self.step = coroutine(self)
def next(self):
try_(self.step.__next__, None, StopIteration)
Backtest(SHORT_DATA, S).run()
class TestOptimize(TestCase):
def test_optimize(self):
bt = Backtest(GOOG.iloc[:100], SmaCross)