Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion backtesting/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,9 @@ def random_ohlc_data(example_data: pd.DataFrame, *,
`frac` is a fraction of data to sample (with replacement). Values greater
than 1 result in oversampling.

An integer `random_state` seeds a reproducible sequence of samples.
Successive samples advance the random state instead of resetting it.

Such random data can be effectively used for stress testing trading
strategy robustness, Monte Carlo simulations, significance testing, etc.

Expand All @@ -355,8 +358,11 @@ def random_ohlc_data(example_data: pd.DataFrame, *,
>>> next(ohlc_generator) # returns new random data
...
"""
sampling_state = (np.random.RandomState(random_state)
if isinstance(random_state, (int, np.integer)) else random_state)

def shuffle(x):
return x.sample(frac=frac, replace=frac > 1, random_state=random_state)
return x.sample(frac=frac, replace=frac > 1, random_state=sampling_state)

if len(example_data.columns.intersection({'Open', 'High', 'Low', 'Close'})) != 4:
raise ValueError("`data` must be a pandas.DataFrame with columns "
Expand Down
12 changes: 12 additions & 0 deletions backtesting/test/_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -997,6 +997,18 @@ def test_random_ohlc_data(self):
self.assertEqual(new_data.shape, GOOG.shape)
self.assertEqual(list(new_data.columns), list(GOOG.columns))

def test_random_ohlc_data_seeded_varies(self):
generator = random_ohlc_data(GOOG, random_state=42)
first = next(generator)
second = next(generator)
self.assertFalse(first.equals(second))

def test_random_ohlc_data_seeded_reproducible(self):
first = random_ohlc_data(GOOG, random_state=42)
second = random_ohlc_data(GOOG, random_state=42)
for _ in range(3):
assert_frame_equal(next(first), next(second))

def test_compute_stats(self):
stats = Backtest(GOOG, SmaCross).run()
only_long_trades = stats._trades[stats._trades.Size > 0]
Expand Down