diff --git a/Dockerfile b/Dockerfile index 4bfc01b..e2411cf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # # Dockerfile for an image with the currently checked out version of zipline installed. To build: # -# docker build -t quantopian/zipline . +# docker build -t alpacamarkets/alpaca-zipline . # # To run the container: # @@ -9,13 +9,7 @@ # # To access Jupyter when running docker locally (you may need to add NAT rules): # -# https://127.0.0.1 -# -# default password is jupyter. to provide another, see: -# http://jupyter-notebook.readthedocs.org/en/latest/public_server.html#preparing-a-hashed-password -# -# once generated, you can pass the new value via `docker run --env` the first time -# you start the container. +# https://127.0.0.1:8888 # # You can also run an algo using the docker exec command. For example: # @@ -67,23 +61,14 @@ RUN pip install 'numpy>=1.11.1,<2.0.0' \ RUN pip install git+https://github.com/alpacahq/zipline@98e860b55c9fc4a8a825fe6c0f558b0fb2866bf8 RUN pip install alpaca-trade-api==0.10.0 -# -# This is then only file we need from source to remain in the -# image after build and install. -# - -# ADD ./etc/docker_cmd.sh / - -# -# make port available. /zipline is made a volume -# for developer testing. -# EXPOSE ${NOTEBOOK_PORT} +ADD ./extension.py /root/.zipline/extension.py # # start the jupyter server # WORKDIR ${PROJECT_DIR} -# CMD /docker_cmd.sh +ADD ./start-jupyter.sh / +CMD /start-jupyter.sh diff --git a/extension.py b/extension.py new file mode 100644 index 0000000..e36534c --- /dev/null +++ b/extension.py @@ -0,0 +1,90 @@ +from zipline.data import bundles +from click import progressbar +from io import BytesIO +import requests +import tarfile + + +def download_with_progress(url, chunk_size, **progress_kwargs): + """ + Download streaming data from a URL, printing progress information to the + terminal. + + Parameters + ---------- + url : str + A URL that can be understood by ``requests.get``. + chunk_size : int + Number of bytes to read at a time from requests. + **progress_kwargs + Forwarded to click.progressbar. + + Returns + ------- + data : BytesIO + A BytesIO containing the downloaded data. + """ + resp = requests.get(url, stream=True) + resp.raise_for_status() + + total_size = int(resp.headers['content-length']) + data = BytesIO() + with progressbar(length=total_size, **progress_kwargs) as pbar: + for chunk in resp.iter_content(chunk_size=chunk_size): + data.write(chunk) + pbar.update(len(chunk)) + + data.seek(0) + return data + + +def download_without_progress(url): + """ + Download data from a URL, returning a BytesIO containing the loaded data. + + Parameters + ---------- + url : str + A URL that can be understood by ``requests.get``. + + Returns + ------- + data : BytesIO + A BytesIO containing the downloaded data. + """ + resp = requests.get(url) + resp.raise_for_status() + return BytesIO(resp.content) + + +ALPACA_BUNDLE_URL = ( + 'https://s3.amazonaws.com/files.alpaca.markets/bundle/alpaca-bundle.tgz' +) +ONE_MEGABYTE = 1024 * 1024 + + +@bundles.register('alpaca-bundle', create_writers=False) +def alpaca_bundle(environ, + asset_db_writer, + minute_bar_writer, + daily_bar_writer, + adjustment_writer, + calendar, + start_session, + end_session, + cache, + show_progress, + output_dir): + if show_progress: + data = download_with_progress( + ALPACA_BUNDLE_URL, + chunk_size=ONE_MEGABYTE, + label="Downloading Bundle: alpaca-bundle", + ) + else: + data = download_without_progress(ALPACA_BUNDLE_URL) + + with tarfile.open('r', fileobj=data) as tar: + if show_progress: + print("Writing data to %s." % output_dir) + tar.extractall(output_dir) diff --git a/start-jupyter.sh b/start-jupyter.sh new file mode 100755 index 0000000..7af3737 --- /dev/null +++ b/start-jupyter.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +# +# generate configuration and password if this is the first run +# +if [ ! -f /var/tmp/zipline_init ] ; then + jupyter notebook --generate-config + echo "c.NotebookApp.password = ''" >> ${CONFIG_PATH} + touch /var/tmp/zipline_init +fi + +jupyter notebook -y --no-browser --notebook-dir=${PROJECT_DIR} \ + --ip='*' --allow-root --NotebookApp.token= \ + --config=${CONFIG_PATH} \ No newline at end of file