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
12 changes: 11 additions & 1 deletion lumibot/backtesting/backtesting_broker.py
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,8 @@ def process_pending_orders(self, strategy):
#############################
# Get OHLCV data for the asset
#############################
bid = None
ask = None

# Get the OHLCV data for the asset if we're using the YAHOO, CCXT data source
data_source_name = self.data_source.SOURCE.upper()
Expand Down Expand Up @@ -637,13 +639,21 @@ def process_pending_orders(self, strategy):
low = df["low"].iloc[0]
close = df["close"].iloc[0]
volume = df["volume"].iloc[0]
if 'bid' in df.columns and 'ask' in df.columns:
bid = df["bid"].iloc[0]
ask = df["ask"].iloc[0]

#############################
# Determine transaction price.
#############################

if order.type == "market":
price = open
if order.side == "buy" and ask is not None:
price = ask
elif order.side == "sell" and bid is not None:
price = bid
else:
price = open

elif order.type == "limit":
price = self.limit_order(order.limit_price, order.side, open, high, low)
Expand Down
21 changes: 14 additions & 7 deletions lumibot/entities/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -555,13 +555,6 @@ def get_bars(self, dt, length=1, timestep=MIN_TIMESTEP, timeshift=0):
if timestep != "minute" and timestep != "day":
raise ValueError(f"Only minute and day are supported for timestep. You provided: {timestep}")

agg_column_map = {
"open": "first",
"high": "max",
"low": "min",
"close": "last",
"volume": "sum",
}
if timestep == "day" and self.timestep == "minute":
# If the data is minute data and we are requesting daily data then multiply the length by 1440
length = length * 1440
Expand All @@ -576,6 +569,20 @@ def get_bars(self, dt, length=1, timestep=MIN_TIMESTEP, timeshift=0):
if data is None:
return None

agg_column_map = {
"open": "first",
"high": "max",
"low": "min",
"close": "last",
"volume": "sum",
}
# check if 'bid' and 'ask' are in the data and add them to the agg_column_map
if 'bid' in data and 'ask' in data:
agg_column_map['bid'] = "max"
agg_column_map['ask'] = "min"
agg_column_map['bid_size'] = "sum"
agg_column_map['ask_size'] = "sum"

df = pd.DataFrame(data).assign(datetime=lambda df: pd.to_datetime(df['datetime'])).set_index('datetime')
df_result = df.resample(f"{quantity}{unit}").agg(agg_column_map)

Expand Down
2 changes: 1 addition & 1 deletion tests/backtest/test_thetadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ def verify_backtest_results(self, theta_strat_obj):
assert 130.0 < theta_strat_obj.prices[asset_order_id] < 140.0, "Valid asset price between 130 and 140"
assert 130.0 < stock_order.get_fill_price() < 140.0, "Valid asset price between 130 and 140"
assert theta_strat_obj.prices[option_order_id] == 4.5, "Price is $4.5 on 08/01/2023 12:30pm"
assert option_order.get_fill_price() == 4.5, "Fills at 1st candle open price of $4.10 on 08/01/2023"
assert option_order.get_fill_price() == 4.55, "Fills at 1st candle open price of $4.10 on 08/01/2023"

assert option_order.is_filled()

Expand Down