HTTPError: BAD REQUEST 'attach_pipeline"

I've written the following strategy:

%%writefile pv_strategy6.py

import zipline.api as algo
from zipline.finance import commission, slippage
from zipline.pipeline import Pipeline
from zipline.pipeline.data import USEquityPricing
from zipline.pipeline.factors import AverageDollarVolume
from zipline.pipeline.factors import CustomFactor

MONTH = 21
N_LONGS = 50
N_SHORTS = 50

class ParkinsonVolatility(CustomFactor):
inputs = [USEquityPricing.high, USEquityPricing.low]
window_length = MONTH

def compute(self, today, assets, out, highs, lows):
    rs = (1.0 / (4.0 * np.log(2.0))) * (np.log(highs / lows)) ** 2.0
    vol = np.sqrt(252 * np.nanmean(rs, axis=0))
    out[:] = (vol - np.mean(vol)) / np.std(vol)

def make_pipeline():
pipe = Pipeline(
columns={
"parkinson": ParkinsonVolatility()
},
screen=AverageDollarVolume(window_length=30) > 10e6
)
return pipe

def initialize(context):
attach_pipeline(compute_factors(), "factor_pipeline")
schedule_function(
rebalance,
date_rules.week_start(),
time_rules.market_open(),
)

set_commission(
    us_equities=commission.PerShare(
        cost=0.005,
        min_trade_cost=2.0
    )
)
set_slippage(
    us_equities=slippage.VolumeShareSlippage(
        volume_limit=0.0025, 
        price_impact=0.01
    )
)

def before_trading_start(context, data):
context.factor_data = pipeline_output("factor_pipeline")
record(factor_data=context.factor_data.ranking)

assets = context.factor_data.index
record(prices=data.current(assets, "price"))

def rebalance(context, data):

factor_data = context.factor_data
assets = factor_data.index

longs = assets[factor_data.longs]
shorts = assets[factor_data.shorts]
divest = context.portfolio.positions.keys() - longs.union(shorts)

# Print some portfolio details.
print(
    f"{get_datetime().date()} | Longs {len(longs)} | Shorts | {len(shorts)} | {context.portfolio.portfolio_value}"
)

# Execute the trades with equal weight
exec_trades(data, assets=divest, target_percent=0)
exec_trades(data, assets=longs, target_percent=1 / N_LONGS) #if N_LONGS else 0)
exec_trades(data, assets=shorts, target_percent=-1 / N_SHORTS) #if N_SHORTS else 0)

def exec_trades(data, assets, target_percent):
# Loop through every asset...
for asset in assets:
# ...if the asset is tradeable and there are no open orders...
if data.can_trade(asset) and not get_open_orders(asset):
# ...execute the order against the target percent
order_target_percent(asset, target_percent)

This code executes in Jupyter without any errors. I then attempt to run the backtest as follows:

from quantrocket.zipline import backtest
backtest("pv_strategy6",
progress="M", # Use for long running test. 'D'= daily, 'W'=weeky, 'M'=monthly, 'Q'=quarterly,'A'=annually
start_date="2017-01-01", end_date="2018-01-01",
filepath_or_buffer="PV_results.csv") # are you nameing the file of the backtest here?

And I'm receiving the following error:


HTTPError Traceback (most recent call last)
Input In [85], in <cell line: 7>()
1 # Strategy files should be placed in /codeload/zipline/, that is, inside a zipline subdirectory in the
2 # JupyterLab file browser. The filename without the .py extension is the code you will use to refer to the strategy in
3 # backtesting and trading. For example, if you name the file dma.py, the strategy's code is dma. Use this code to
4 # run a backtest.
6 from quantrocket.zipline import backtest
----> 7 backtest("pv_strategy6",
8 progress="M", # Use for long running test. 'D'= daily, 'W'=weeky, 'M'=monthly, 'Q'=quarterly,'A'=annually
9 start_date="2017-01-01", end_date="2018-01-01",
10 filepath_or_buffer="PV_results.csv") # are you nameing the file of the backtest here?

File /opt/conda/lib/python3.9/site-packages/quantrocket/zipline.py:817, in backtest(strategy, data_frequency, capital_base, bundle, start_date, end_date, progress, params, filepath_or_buffer)
813 _params["progress"] = progress
815 response = houston.post("/zipline/backtests/{0}".format(strategy), params=_params, timeout=606096)
--> 817 houston.raise_for_status_with_json(response)
819 filepath_or_buffer = filepath_or_buffer or sys.stdout
820 write_response_to_filepath_or_buffer(filepath_or_buffer, response)

File /opt/conda/lib/python3.9/site-packages/quantrocket/houston.py:225, in Houston.raise_for_status_with_json(response)
223 e.json_response = {}
224 e.args = e.args + ("please check the logs for more details",)
--> 225 raise e

File /opt/conda/lib/python3.9/site-packages/quantrocket/houston.py:217, in Houston.raise_for_status_with_json(response)
212 """
213 Raises 400/500 error codes, attaching a json response to the
214 exception, if possible.
215 """
216 try:
--> 217 response.raise_for_status()
218 except requests.exceptions.HTTPError as e:
219 try:

File /opt/conda/lib/python3.9/site-packages/requests/models.py:1021, in Response.raise_for_status(self)
1016 http_error_msg = (
1017 f"{self.status_code} Server Error: {reason} for url: {self.url}"
1018 )
1020 if http_error_msg:
-> 1021 raise HTTPError(http_error_msg, response=self)

HTTPError: ('400 Client Error: BAD REQUEST for url: http://houston/zipline/backtests/pv_strategy6?start_date=2017-01-01&end_date=2018-01-01&progress=M', {'status': 'error', 'msg': "name 'attach_pipeline' is not defined (see detailed logs for full traceback)"})

Any assistance / insights would be appreciated.

Thanks.

That variable as well as others in your file are undefined. The function you’re calling is part of zipline.api which you’ve imported as algo, so you need to use algo.attach_pipeline(…), not just attach_pipeline(…). To identify all of the undefined variables, open the file in JupyterLab and click Show Diagnostics Panel.

On a side note, the forum will format your code blocks better if you type three backticks on the line before and after it.

```
your code here

```