FAQs
How to…
… get your version of PyBroker?
[1]:
import pybroker
pybroker.__version__
[1]:
'1.1.27'
… get data for another symbol?
[2]:
from pybroker import ExecContext, Strategy, YFinance, highest
def exec_fn(ctx: ExecContext):
if ctx.symbol == 'NVDA':
other_bar_data = ctx.foreign('AMD')
other_highest = ctx.indicator('high_10d', 'AMD')
strategy = Strategy(YFinance(), start_date='1/1/2022', end_date='1/1/2023')
strategy.add_execution(
exec_fn, ['NVDA', 'AMD'], indicators=highest('high_10d', 'close', period=10))
result = strategy.backtest()
Backtesting: 2022-01-01 00:00:00 to 2023-01-01 00:00:00
Loading bar data...
[*********************100%***********************] 2 of 2 completed
Loaded bar data: 0:00:00
Computing indicators...
100% (2 of 2) |##########################| Elapsed Time: 0:00:01 Time: 0:00:01
Test split: 2022-01-03 00:00:00 to 2022-12-30 00:00:00
100% (251 of 251) |######################| Elapsed Time: 0:00:00 Time: 0:00:00
Finished backtest: 0:00:02
You can also retrieve models, predictions, and other data for other symbols. For more information, refer to the ExecContext reference documentation.
… set a limit price?
Set buy_limit_price or sell_limit_price:
[3]:
from pybroker import ExecContext, Strategy, YFinance
def buy_fn(ctx: ExecContext):
if not ctx.long_pos():
ctx.buy_shares = 100
ctx.buy_limit_price = ctx.close[-1] * 0.99
ctx.hold_bars = 10
strategy = Strategy(YFinance(), start_date='3/1/2022', end_date='1/1/2023')
strategy.add_execution(buy_fn, 'SPY')
result = strategy.backtest()
result.orders.head(10)
Backtesting: 2022-03-01 00:00:00 to 2023-01-01 00:00:00
Loading bar data...
[*********************100%***********************] 1 of 1 completed
Loaded bar data: 0:00:00
Test split: 2022-03-01 00:00:00 to 2022-12-30 00:00:00
100% (212 of 212) |######################| Elapsed Time: 0:00:00 Time: 0:00:00
Finished backtest: 0:00:00
[3]:
type | symbol | date | shares | limit_price | fill_price | fees | |
---|---|---|---|---|---|---|---|
id | |||||||
1 | buy | SPY | 2022-03-04 | 100 | 431.35 | 430.62 | 0.0 |
2 | sell | SPY | 2022-03-18 | 100 | NaN | 441.04 | 0.0 |
3 | buy | SPY | 2022-04-06 | 100 | 446.52 | 446.20 | 0.0 |
4 | sell | SPY | 2022-04-21 | 100 | NaN | 443.56 | 0.0 |
5 | buy | SPY | 2022-04-22 | 100 | 433.68 | 431.76 | 0.0 |
6 | sell | SPY | 2022-05-06 | 100 | NaN | 410.26 | 0.0 |
7 | buy | SPY | 2022-05-09 | 100 | 407.23 | 401.46 | 0.0 |
8 | sell | SPY | 2022-05-23 | 100 | NaN | 394.06 | 0.0 |
9 | buy | SPY | 2022-05-24 | 100 | 392.95 | 391.05 | 0.0 |
10 | sell | SPY | 2022-06-08 | 100 | NaN | 413.10 | 0.0 |
… set the fill price?
Set buy_fill_price and sell_fill_price. See PriceType for options.
[4]:
from pybroker import ExecContext, PriceType, Strategy, YFinance
def exec_fn(ctx: ExecContext):
if ctx.long_pos():
ctx.buy_shares = 100
ctx.buy_fill_price = PriceType.AVERAGE
else:
ctx.sell_shares = 100
ctx.sell_fill_price = PriceType.CLOSE
strategy = Strategy(YFinance(), start_date='3/1/2022', end_date='1/1/2023')
strategy.add_execution(buy_fn, 'SPY')
result = strategy.backtest()
result.orders.head(10)
Backtesting: 2022-03-01 00:00:00 to 2023-01-01 00:00:00
Loading bar data...
[*********************100%***********************] 1 of 1 completed
Loaded bar data: 0:00:00
Test split: 2022-03-01 00:00:00 to 2022-12-30 00:00:00
100% (212 of 212) |######################| Elapsed Time: 0:00:00 Time: 0:00:00
Finished backtest: 0:00:00
[4]:
type | symbol | date | shares | limit_price | fill_price | fees | |
---|---|---|---|---|---|---|---|
id | |||||||
1 | buy | SPY | 2022-03-04 | 100 | 431.35 | 430.62 | 0.0 |
2 | sell | SPY | 2022-03-18 | 100 | NaN | 441.04 | 0.0 |
3 | buy | SPY | 2022-04-06 | 100 | 446.52 | 446.20 | 0.0 |
4 | sell | SPY | 2022-04-21 | 100 | NaN | 443.56 | 0.0 |
5 | buy | SPY | 2022-04-22 | 100 | 433.68 | 431.76 | 0.0 |
6 | sell | SPY | 2022-05-06 | 100 | NaN | 410.26 | 0.0 |
7 | buy | SPY | 2022-05-09 | 100 | 407.23 | 401.46 | 0.0 |
8 | sell | SPY | 2022-05-23 | 100 | NaN | 394.06 | 0.0 |
9 | buy | SPY | 2022-05-24 | 100 | 392.95 | 391.05 | 0.0 |
10 | sell | SPY | 2022-06-08 | 100 | NaN | 413.10 | 0.0 |
… get current positions?
[5]:
from pybroker import ExecContext, Strategy, YFinance
def exec_fn(ctx: ExecContext):
# Get all positions.
all_positions = tuple(ctx.positions())
# Get all long positions.
long_positions = tuple(ctx.long_positions())
# Get all short positions.
short_positions = tuple(ctx.short_positions())
# Get long position for current ctx.symbol.
long_position = ctx.long_pos()
# Get short position for a symbol.
short_position = ctx.short_pos('QQQ')
strategy = Strategy(YFinance(), start_date='3/1/2022', end_date='1/1/2023')
strategy.add_execution(exec_fn, ['SPY', 'QQQ'])
result = strategy.backtest()
Backtesting: 2022-03-01 00:00:00 to 2023-01-01 00:00:00
Loading bar data...
[*********************100%***********************] 2 of 2 completed
Loaded bar data: 0:00:00
Test split: 2022-03-01 00:00:00 to 2022-12-30 00:00:00
100% (212 of 212) |######################| Elapsed Time: 0:00:00 Time: 0:00:00
Finished backtest: 0:00:00
… use custom column data?
Register your custom columns with pybroker.register_columns:
[6]:
import pybroker
from pybroker import ExecContext, Strategy, YFinance
yf = YFinance()
df = yf.query('SPY', start_date='1/1/2022', end_date='1/1/2023')
df['buy_signal'] = 1
def buy_fn(ctx: ExecContext):
if not ctx.long_pos() and ctx.buy_signal[-1] == 1:
ctx.buy_shares = 100
ctx.hold_bars = 1
pybroker.register_columns('buy_signal')
strategy = Strategy(df, start_date='3/1/2022', end_date='1/1/2023')
strategy.add_execution(buy_fn, 'SPY')
result = strategy.backtest()
result.orders.head(10)
Loading bar data...
[*********************100%***********************] 1 of 1 completed
Loaded bar data: 0:00:00
Backtesting: 2022-03-01 00:00:00 to 2023-01-01 00:00:00
Test split: 2022-03-01 00:00:00 to 2022-12-30 00:00:00
100% (212 of 212) |######################| Elapsed Time: 0:00:00 Time: 0:00:00
Finished backtest: 0:00:00
[6]:
type | symbol | date | shares | limit_price | fill_price | fees | |
---|---|---|---|---|---|---|---|
id | |||||||
1 | buy | SPY | 2022-03-02 | 100 | NaN | 435.65 | 0.0 |
2 | sell | SPY | 2022-03-03 | 100 | NaN | 437.45 | 0.0 |
3 | buy | SPY | 2022-03-04 | 100 | NaN | 430.62 | 0.0 |
4 | sell | SPY | 2022-03-07 | 100 | NaN | 425.83 | 0.0 |
5 | buy | SPY | 2022-03-08 | 100 | NaN | 421.16 | 0.0 |
6 | sell | SPY | 2022-03-09 | 100 | NaN | 426.17 | 0.0 |
7 | buy | SPY | 2022-03-10 | 100 | NaN | 423.43 | 0.0 |
8 | sell | SPY | 2022-03-11 | 100 | NaN | 424.15 | 0.0 |
9 | buy | SPY | 2022-03-14 | 100 | NaN | 420.17 | 0.0 |
10 | sell | SPY | 2022-03-15 | 100 | NaN | 422.63 | 0.0 |
… place an order more than one bar ahead?
Use the buy_delay and sell_delay configuration options:
[7]:
from pybroker import ExecContext, Strategy, StrategyConfig, YFinance
def buy_fn(ctx: ExecContext):
if not tuple(ctx.pending_orders()) and not ctx.long_pos():
ctx.buy_shares = 100
ctx.hold_bars = 1
config = StrategyConfig(buy_delay=5)
strategy = Strategy(YFinance(), start_date='3/1/2022', end_date='1/1/2023', config=config)
strategy.add_execution(buy_fn, 'SPY')
result = strategy.backtest()
result.orders.head(10)
Backtesting: 2022-03-01 00:00:00 to 2023-01-01 00:00:00
Loading bar data...
[*********************100%***********************] 1 of 1 completed
Loaded bar data: 0:00:00
Test split: 2022-03-01 00:00:00 to 2022-12-30 00:00:00
100% (212 of 212) |######################| Elapsed Time: 0:00:00 Time: 0:00:00
Finished backtest: 0:00:00
[7]:
type | symbol | date | shares | limit_price | fill_price | fees | |
---|---|---|---|---|---|---|---|
id | |||||||
1 | buy | SPY | 2022-03-08 | 100 | NaN | 421.16 | 0.0 |
2 | sell | SPY | 2022-03-09 | 100 | NaN | 426.17 | 0.0 |
3 | buy | SPY | 2022-03-16 | 100 | NaN | 430.24 | 0.0 |
4 | sell | SPY | 2022-03-17 | 100 | NaN | 437.13 | 0.0 |
5 | buy | SPY | 2022-03-24 | 100 | NaN | 447.63 | 0.0 |
6 | sell | SPY | 2022-03-25 | 100 | NaN | 450.71 | 0.0 |
7 | buy | SPY | 2022-04-01 | 100 | NaN | 451.30 | 0.0 |
8 | sell | SPY | 2022-04-04 | 100 | NaN | 454.59 | 0.0 |
9 | buy | SPY | 2022-04-11 | 100 | NaN | 442.20 | 0.0 |
10 | sell | SPY | 2022-04-12 | 100 | NaN | 441.20 | 0.0 |
… cancel pending orders?
See the cancel_pending_order and cancel_all_pending_orders methods.
[8]:
from pybroker import ExecContext, Strategy, StrategyConfig, YFinance
def buy_fn(ctx: ExecContext):
pending = tuple(ctx.pending_orders())
if not pending and not ctx.long_pos():
ctx.buy_shares = 100
ctx.hold_bars = 1
if pending and ctx.close[-1] < 430:
ctx.cancel_all_pending_orders(ctx.symbol)
config = StrategyConfig(buy_delay=5)
strategy = Strategy(YFinance(), start_date='3/1/2022', end_date='1/1/2023', config=config)
strategy.add_execution(buy_fn, 'SPY')
result = strategy.backtest()
result.orders.head(10)
Backtesting: 2022-03-01 00:00:00 to 2023-01-01 00:00:00
Loading bar data...
[*********************100%***********************] 1 of 1 completed
Loaded bar data: 0:00:00
Test split: 2022-03-01 00:00:00 to 2022-12-30 00:00:00
100% (212 of 212) |######################| Elapsed Time: 0:00:00 Time: 0:00:00
Finished backtest: 0:00:00
[8]:
type | symbol | date | shares | limit_price | fill_price | fees | |
---|---|---|---|---|---|---|---|
id | |||||||
1 | buy | SPY | 2022-03-23 | 100 | NaN | 446.10 | 0.0 |
2 | sell | SPY | 2022-03-24 | 100 | NaN | 447.63 | 0.0 |
3 | buy | SPY | 2022-03-31 | 100 | NaN | 454.96 | 0.0 |
4 | sell | SPY | 2022-04-01 | 100 | NaN | 451.30 | 0.0 |
5 | buy | SPY | 2022-04-08 | 100 | NaN | 448.29 | 0.0 |
6 | sell | SPY | 2022-04-11 | 100 | NaN | 442.20 | 0.0 |
7 | buy | SPY | 2022-04-19 | 100 | NaN | 441.74 | 0.0 |
8 | sell | SPY | 2022-04-20 | 100 | NaN | 445.53 | 0.0 |
… persist data across bars?
Use the ExecContext#session dictionary:
[9]:
from pybroker import ExecContext, Strategy, YFinance
def buy_fn(ctx: ExecContext):
if not ctx.long_pos():
ctx.buy_shares = 100
ctx.hold_bars = 1
count = ctx.session.get('entry_count', 0)
ctx.session['entry_count'] = count + 1
strategy = Strategy(YFinance(), start_date='1/1/2022', end_date='1/1/2023')
strategy.add_execution(buy_fn, 'SPY')
result = strategy.backtest()
Backtesting: 2022-01-01 00:00:00 to 2023-01-01 00:00:00
Loading bar data...
[*********************100%***********************] 1 of 1 completed
Loaded bar data: 0:00:00
Test split: 2022-01-03 00:00:00 to 2022-12-30 00:00:00
100% (251 of 251) |######################| Elapsed Time: 0:00:00 Time: 0:00:00
Finished backtest: 0:00:00
… exit a position?
Use sell_all_shares() or cover_all_shares() to liquidate a position:
[10]:
from pybroker import ExecContext, Strategy, YFinance
def buy_fn(ctx: ExecContext):
pos = ctx.long_pos()
if not pos:
ctx.buy_shares = 100
elif pos.bars > 30:
ctx.sell_all_shares()
strategy = Strategy(YFinance(), start_date='1/1/2022', end_date='1/1/2023')
strategy.add_execution(buy_fn, 'SPY')
result = strategy.backtest()
result.trades
Backtesting: 2022-01-01 00:00:00 to 2023-01-01 00:00:00
Loading bar data...
[*********************100%***********************] 1 of 1 completed
Loaded bar data: 0:00:00
Test split: 2022-01-03 00:00:00 to 2022-12-30 00:00:00
100% (251 of 251) |######################| Elapsed Time: 0:00:00 Time: 0:00:00
Finished backtest: 0:00:00
[10]:
type | symbol | entry_date | exit_date | entry | exit | shares | pnl | return_pct | agg_pnl | bars | pnl_per_bar | stop | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
id | |||||||||||||
1 | long | SPY | 2022-01-04 | 2022-02-18 | 477.78 | 435.24 | 100 | -4254.0 | -8.90 | -4254.0 | 32 | -132.94 | None |
2 | long | SPY | 2022-02-22 | 2022-04-07 | 430.68 | 447.11 | 100 | 1643.0 | 3.81 | -2611.0 | 32 | 51.34 | None |
3 | long | SPY | 2022-04-08 | 2022-05-25 | 448.29 | 395.67 | 100 | -5262.0 | -11.74 | -7873.0 | 32 | -164.44 | None |
4 | long | SPY | 2022-05-26 | 2022-07-14 | 402.75 | 375.04 | 100 | -2771.0 | -6.88 | -10644.0 | 32 | -86.59 | None |
5 | long | SPY | 2022-07-15 | 2022-08-30 | 382.90 | 400.05 | 100 | 1715.0 | 4.48 | -8929.0 | 32 | 53.59 | None |
6 | long | SPY | 2022-08-31 | 2022-10-17 | 398.14 | 362.63 | 100 | -3551.0 | -8.92 | -12480.0 | 32 | -110.97 | None |
7 | long | SPY | 2022-10-18 | 2022-12-02 | 371.49 | 405.00 | 100 | 3351.0 | 9.02 | -9129.0 | 32 | 104.72 | None |
… process multiple symbols at once?
Use set_before_exec or set_after_exec:
[11]:
from pybroker import ExecContext, Strategy, YFinance
def long_short_fn(ctxs: dict[str, ExecContext]):
nvda_ctx = ctxs['NVDA']
amd_ctx = ctxs['AMD']
if nvda_ctx.long_pos() or amd_ctx.short_pos():
return
if nvda_ctx.bars >= 2 and nvda_ctx.close[-1] < nvda_ctx.low[-2]:
nvda_ctx.buy_shares = 100
nvda_ctx.hold_bars = 3
amd_ctx.sell_shares = 100
amd_ctx.hold_bars = 3
strategy = Strategy(YFinance(), start_date='1/1/2022', end_date='1/1/2023')
strategy.add_execution(None, ['NVDA', 'AMD'])
strategy.set_after_exec(long_short_fn)
result = strategy.backtest()
result.trades
Backtesting: 2022-01-01 00:00:00 to 2023-01-01 00:00:00
Loading bar data...
[*********************100%***********************] 2 of 2 completed
Loaded bar data: 0:00:00
Test split: 2022-01-03 00:00:00 to 2022-12-30 00:00:00
100% (251 of 251) |######################| Elapsed Time: 0:00:00 Time: 0:00:00
Finished backtest: 0:00:00
[11]:
type | symbol | entry_date | exit_date | entry | exit | shares | pnl | return_pct | agg_pnl | bars | pnl_per_bar | stop | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
id | |||||||||||||
1 | long | NVDA | 2022-01-05 | 2022-01-10 | 284.74 | 265.57 | 100 | -1917.0 | -6.73 | -1917.0 | 3 | -639.00 | bar |
2 | short | AMD | 2022-01-05 | 2022-01-10 | 139.52 | 128.72 | 100 | 1080.0 | 8.39 | -837.0 | 3 | 360.00 | bar |
3 | long | NVDA | 2022-01-14 | 2022-01-20 | 267.04 | 248.28 | 100 | -1876.0 | -7.03 | -2713.0 | 3 | -625.33 | bar |
4 | short | AMD | 2022-01-14 | 2022-01-20 | 134.21 | 124.96 | 100 | 925.0 | 7.40 | -1788.0 | 3 | 308.33 | bar |
5 | long | NVDA | 2022-01-21 | 2022-01-26 | 240.43 | 231.79 | 100 | -864.0 | -3.59 | -2652.0 | 3 | -288.00 | bar |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
76 | short | AMD | 2022-12-07 | 2022-12-12 | 70.33 | 69.10 | 100 | 123.0 | 1.78 | 1863.0 | 3 | 41.00 | bar |
77 | long | NVDA | 2022-12-15 | 2022-12-20 | 170.10 | 160.81 | 100 | -929.0 | -5.46 | 934.0 | 3 | -309.67 | bar |
78 | short | AMD | 2022-12-15 | 2022-12-20 | 67.17 | 64.79 | 100 | 238.0 | 3.67 | 1172.0 | 3 | 79.33 | bar |
79 | long | NVDA | 2022-12-21 | 2022-12-27 | 163.65 | 145.78 | 100 | -1787.0 | -10.92 | -615.0 | 3 | -595.67 | bar |
80 | short | AMD | 2022-12-21 | 2022-12-27 | 66.53 | 63.62 | 100 | 291.0 | 4.57 | -324.0 | 3 | 97.00 | bar |
80 rows × 13 columns
… annualize the Sharpe Ratio?
Set the bars_per_year configuration option. For example, setting a value of 252
would be used to annualize daily returns.
[12]:
from pybroker import ExecContext, Strategy, StrategyConfig, YFinance
def buy_fn(ctx: ExecContext):
if ctx.long_pos() or ctx.bars < 2:
return
if ctx.close[-1] < ctx.high[-2]:
ctx.buy_shares = 100
ctx.hold_bars = 1
config = StrategyConfig(bars_per_year=252)
strategy = Strategy(YFinance(), start_date='1/1/2022', end_date='1/1/2023', config=config)
strategy.add_execution(buy_fn, 'SPY')
result = strategy.backtest()
result.metrics.sharpe
Backtesting: 2022-01-01 00:00:00 to 2023-01-01 00:00:00
Loading bar data...
[*********************100%***********************] 1 of 1 completed
Loaded bar data: 0:00:00
Test split: 2022-01-03 00:00:00 to 2022-12-30 00:00:00
100% (251 of 251) |######################| Elapsed Time: 0:00:00 Time: 0:00:00
Finished backtest: 0:00:00
[12]:
-0.8930247224724036
… limit margin used for short selling?
By default, PyBroker does not limit the amount of margin that can be used for short selling. However, you can manually limit the amount of margin that can be used:
[13]:
import pybroker
from pybroker import ExecContext
from decimal import Decimal
def short_fn(ctx: ExecContext):
margin_requirement = Decimal('0.25')
max_margin = ctx.total_equity / margin_requirement - ctx.total_equity
if not ctx.short_pos():
available_margin = max_margin - ctx.total_margin
ctx.sell_shares = ctx.calc_target_shares(0.5, cash=available_margin)
ctx.hold_bars = 1
strategy = Strategy(YFinance(), start_date='1/1/2022', end_date='1/1/2023')
strategy.add_execution(short_fn, ['NVDA', 'AMD'])
result = strategy.backtest()
result.portfolio.head(10)
Backtesting: 2022-01-01 00:00:00 to 2023-01-01 00:00:00
Loading bar data...
[*********************100%***********************] 2 of 2 completed
Loaded bar data: 0:00:00
Test split: 2022-01-03 00:00:00 to 2022-12-30 00:00:00
100% (251 of 251) |######################| Elapsed Time: 0:00:00 Time: 0:00:00
Finished backtest: 0:00:00
[13]:
cash | equity | margin | market_value | pnl | unrealized_pnl | fees | |
---|---|---|---|---|---|---|---|
date | |||||||
2022-01-03 | 100000.00 | 100000.00 | 0.00 | 100000.00 | 0.00 | 0.00 | 0.0 |
2022-01-04 | 100000.00 | 100000.00 | 289702.46 | 102722.18 | 0.00 | 2722.18 | 0.0 |
2022-01-05 | 111667.90 | 111667.90 | 0.00 | 111667.90 | 11667.90 | 0.00 | 0.0 |
2022-01-06 | 111667.90 | 111667.90 | 338321.57 | 107432.09 | 11667.90 | -4235.81 | 0.0 |
2022-01-07 | 112472.56 | 112472.56 | 0.00 | 112472.56 | 12472.56 | 0.00 | 0.0 |
2022-01-10 | 112472.56 | 112472.56 | 338302.00 | 103062.55 | 12472.56 | -9410.01 | 0.0 |
2022-01-11 | 98536.05 | 98536.05 | 0.00 | 98536.05 | -1463.95 | 0.00 | 0.0 |
2022-01-12 | 98536.05 | 98536.05 | 296592.41 | 99830.87 | -1463.95 | 1294.82 | 0.0 |
2022-01-13 | 103550.41 | 103550.41 | 0.00 | 103550.41 | 3550.41 | 0.00 | 0.0 |
2022-01-14 | 103550.41 | 103550.41 | 317490.89 | 99036.58 | 3550.41 | -4513.83 | 0.0 |
… get and set a global parameter?
[14]:
import pybroker
# Set parameter.
pybroker.param('lookback', 100)
# Get parameter.
pybroker.param('lookback')
[14]:
100
… apply random slippage?
Set a RandomSlippageModel:
[15]:
from pybroker import ExecContext, RandomSlippageModel, Strategy, YFinance
def buy_fn(ctx: ExecContext):
if not ctx.long_pos():
ctx.buy_shares = 100
ctx.hold_bars = 1
slippage = RandomSlippageModel(min_pct=1.0, max_pct=5.0) # Slippage of 1-5%
strategy = Strategy(YFinance(), start_date='3/1/2022', end_date='1/1/2023')
strategy.set_slippage_model(slippage)
strategy.add_execution(buy_fn, 'SPY')
result = strategy.backtest()
result.orders.head(10)
Backtesting: 2022-03-01 00:00:00 to 2023-01-01 00:00:00
Loading bar data...
[*********************100%***********************] 1 of 1 completed
Loaded bar data: 0:00:00
Test split: 2022-03-01 00:00:00 to 2022-12-30 00:00:00
100% (212 of 212) |######################| Elapsed Time: 0:00:00 Time: 0:00:00
Finished backtest: 0:00:00
[15]:
type | symbol | date | shares | limit_price | fill_price | fees | |
---|---|---|---|---|---|---|---|
id | |||||||
1 | buy | SPY | 2022-03-02 | 98 | NaN | 435.65 | 0.0 |
2 | sell | SPY | 2022-03-03 | 98 | NaN | 437.45 | 0.0 |
3 | buy | SPY | 2022-03-04 | 98 | NaN | 430.62 | 0.0 |
4 | sell | SPY | 2022-03-07 | 98 | NaN | 425.83 | 0.0 |
5 | buy | SPY | 2022-03-08 | 98 | NaN | 421.16 | 0.0 |
6 | sell | SPY | 2022-03-09 | 98 | NaN | 426.17 | 0.0 |
7 | buy | SPY | 2022-03-10 | 97 | NaN | 423.43 | 0.0 |
8 | sell | SPY | 2022-03-11 | 97 | NaN | 424.15 | 0.0 |
9 | buy | SPY | 2022-03-14 | 97 | NaN | 420.17 | 0.0 |
10 | sell | SPY | 2022-03-15 | 97 | NaN | 422.63 | 0.0 |