Package: pylivetrader
pylivetraderpylivetrader is a simple python live trading framework with zipline interface.
The main purpose is to run algorithms developed in the Quantopian platform in
live trading via broker API. In order to convert your algorithm for pylivetrader,
please read themigration document.example codecheck out theexamplesfolder. you will find there the following examples:simple MACD "momentum" tradingusing pipeline-live to screen top stocks every daya potfolio optimizer (used to optimize an existing porfolio. not to buy new
stocks)each sample code contains a readme file and a smoke runner (read further to
understand what smoke is)Simple UsageHere is the example dual moving average algorithm (byquantopian/zipline).
We provide mostly the same API interfaces with zipline.frompylivetrader.apiimportorder_target,symboldefinitialize(context):context.i=0context.asset=symbol('AAPL')defhandle_data(context,data):# Compute averages# data.history() has to be called with the same params# from above and returns a pandas dataframe.short_mavg=data.history(context.asset,'price',bar_count=100,frequency="1m").mean()long_mavg=data.history(context.asset,'price',bar_count=300,frequency="1m").mean()# Trading logicifshort_mavg>long_mavg:# order_target orders as many shares as needed to# achieve the desired number of shares.order_target(context.asset,100)elifshort_mavg<long_mavg:order_target(context.asset,0)You can run your algorithm from the CLI tool namedpylivetrader, simply
like below. Then your algorithm starts running with broker API.
You don't need the data bundle file in advance unlike zipline does.$pylivetraderrun-falgo.py--backend-configconfig.yamlConfig file is just simple yaml or json format.$ cat config.yaml
key_id: BROKER_API_KEY
secret: BROKER_SECRET
base_url: https://paper-api.alpaca.markets
feed: iex  # <== change to pro if you have a paid accountUsage with redisIf you are running pylivetrader in an environment with an ephemeral file store and need your context
to persist across restarts, you can use the redis storage engine. This is useful if you launch in a
place like heroku.To use this, you must install the redis-py library.$pipinstallredisAfter that everything is the same as above, except theruncommand looks like the following:$pylivetraderrun-falgo.py--backend-configconfig.yaml--storage-engineredisAssuming you have redis running, this will now serialize your context object to and from redis.InstallationInstall with pip. **pylivetrader currently supports only Python 3.6.$ python3.6 -m venv venv
$ source venv/bin/activate
(venv)$ pip install pylivetraderAdditionally, pylivetrader works well withpipeline-live.Command Referencerunpylivetrader runstarts live trading using your algorithm script. It starts
by calling theinitialize()function if any, and waits until the market opens.
It calls thebefore_trading_startfunction if it is 8:45 ET (45 minutes
before the session starts) or if it starts after that. Once the session
starts, it calls thehandle_data()function every minute until the
session ends, or any functions that are registered byschedule_functionAPI.The options are as follows-for--file: the file path to the algorithm source-bor--backend: the name of backend to use--backend-config: the yaml file for backend parameters--storage-engine: the storage engine to use for persisting the context. ('file' or 'redis')-sor--statefile: the file path to the persisted state file (look for the State Management section below)-ror--retry: the algorithm runner continues execution in the event a general exception is raised-lor--log-level: the minimum level of log which will be written ('DEBUG', 'INFO', 'WARNING', 'ERROR', or 'CRITICAL')shellpylivetrader shellgoes into the IPython interactive shell mode as if you are
in the algorithm script namespace. It means, you can call Algorithm API
such assymbol()anddata.history()so you can check the behavior
of each operation.$ pylivetrader shell algo.pyThe options are as follows-for--file: the file path to the algorithm source-bor--backend: the name of backend to use--backend-config: the yaml file for backend parametersthings you could do with the shellget asset price data. e.g: data.history(symbol("AAPL"), "close", 10, "1d")check if you can trade a certain asset. e.g: data.can_trade(symbol("AAPL"))get your account information: context.accountget your portfolio information: context.account.portfolioget all opened orders: context.get_open_orders()get all orders: context.get_all_orders()get a list of all available assets. eg: context._backend._api.list_assets(asset_class='us_equity')migratepylivetrader migrateallows you to easily migrate your quantopian/zipline code to pylivetrader compatible code.how to run:pylivetradermigrate-izipline_code.py-opylivetrader_compatible.pynow you could execute it with theruncommandnote: we do not support the optimize api by quantopian since it is not a part of ziplineWorking with Pipline-liveYou can see an example usage under the examples folder.To work with pipeline-live you need to do the following steps:Create the pipeline (usually you will create it in a method, convention name ismake_pipeline(). Inside you will define your universe and add factors and filters.DO NOT store the pipe in the context object. We cannot store it to the statefile and you don't need to do it. we store it for you.attach the pipeline to the Algortihm instance. do it like this:context.attach_pipeline(pipe, "my_pipe"). this should be done in theintialize()orbefore_trading_start()methods.Now, to get the output of the pipeline, you do this:context.pipeline_output('my_pipe'). you should call it inhandle_data()or any other method you use the scheduler for.State ManagementOne of the things you need to understand in live trading is that things can
happen and you may need to restart the script or the program dies in the middle
of process due to some external errors. There are couple of things
to know in advance.First, pylivetrader saves the property fields to the disk that you add to
thecontextobject. It is stored in the pickle format and will be
restored on the next startup.Second, because the context properties are restored, you may need to
take care of the extra steps. Often an algorithm is written under
the assumption thatinitialize()is called only once andbefore_trading_start()is called once every morning. If you are
to restart the program in the middle of day, these functions are
called again, with the restored context object. Therefore, you
might need to check if the fields are from the other session
or in the same session to make sure you don't override the
indermediate states in the day.Supported BrokersAlpacaConfiguration by environment variables.$ export APCA_API_KEY_ID={your api key id}
$ export APCA_API_SECRET_KEY={your api secret key}
$ export APCA_API_BASE_URL={https://api.alpaca.markets/ or https://paper-api.alpaca.markets}
$ pylivetrader run -f algo.pyConfiguration by config file. Either yaml or json.$ cat config.yaml
key_id: {your api key id}
secret: {your api secret key}
base_url: {https://api.alpaca.markets/ or https://paper-api.alpaca.markets}
$ pylivetrader run -f algo.py --backend-config config.yamlDockerIf you are already familiar with Docker, it is a good idea to
try ourdocker imagealpacamarkets/pylivetrader.
This has installed pylivetrader so you can start right away without
worrying about your python environment.  See more details in thedockerfilesdirectory.If your algorithm file is calledalgo.py, this could be all you need to run it.dockerrun-v$PWD:/work-w/workalpacamarkets/pylivetraderpylivetraderrun-falgo.pyMake sure you set up environment variables for the backend
(use-e KEY=VALfor docker command).you could also build the docker image from source like this:docker build -t alpaca/pylivetrader-dev -f dockerfiles/Dockerfile-dev .it gives you the power to run it locally and edit or debug the code if you desire.Smoke Testpylivetrader provides a facility for smoke testing. This helps catch
issues such as typos, program errors and simple oversights. The following
is an example of smoke testing.importalgofrompylivetrader.testing.smokeimportharnessdefbefore_run(context,backend):'''This hook is called before algorithm starts.'''# Populate existing positionbackend.set_position('A',10,200,)# modify some fields of context after `initialize(context)` is called_init=context._initializedefwrapper(ctx):_init(ctx)ctx.age[ctx.symbol('A')]=3ctx.age[ctx.symbol('B')]=2context._initialize=wrapperdeftest_algo():pipeline=harness.DefaultPipelineHooker()# run the algorithm under the simulation environmentharness.run_smoke(algo,before_run_hook=before_run,pipeline_hook=pipeline,)if__name__=='__main__':importlogginglogging.basicConfig(level=logging.DEBUG)test_algo()This exercises the algorithm code by harnessing synthetic backend and price data.
Thepylivetrader.testing.smokepackage provides the backend and simulator
clock classes so that it simulates a market day from open to close.By default, the backend creates a universe with 50 stocks ('A' .. 'AX').
For each symbol, you can query synthetic historical price, and orders
are managed within this simulator without having to set up a real remote
backend API. Additionally, you can hook up a couple of code injection
points such asbefore_run_hookandpipeline_hook. In this example,
the setup code creates a pre-populated position in the backend so you can
test the algorithm code path that accepts existing positions.ADefaultPipelineHookerinstance can return a synthetic pipeline result
with the same column names/types, inferred from the pipeline object
given in theattach_pipelineAPI.Again, the purpose of this smoke testing is to actually exercise various
code paths to make sure there are no easy mistakes. This code works well
with standard test frameworks such aspytestand you can easily report
line coverage using those frameworks too.Running Multiple StrategiesThere's a way to execute more than one algorithm at once.The websocket connection is limited to 1 connection per account.For that exact purpose thiswas createdThe steps to execute this are:Run the Alpaca Proxy Agent as described in the project's READMEDefine this env variable:DATA_PROXY_WSto be the address of the proxy agent. (e.g:DATA_PROXY_WS=ws://127.0.0.1:8765)execute your algorithm. it will connect to the servers through the proxy agent allowing you to execute multiple strategies