mirror of
https://github.com/wassname/catalyst.git
synced 2026-09-11 12:00:50 +08:00
DOC: updated examples/buy_and_hodl.py. Added Example Algos and Utilities pages to the documentation
This commit is contained in:
@@ -16,7 +16,6 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
|
||||||
from catalyst import run_algorithm
|
|
||||||
from catalyst.api import (
|
from catalyst.api import (
|
||||||
order_target_value,
|
order_target_value,
|
||||||
symbol,
|
symbol,
|
||||||
@@ -27,15 +26,10 @@ from catalyst.api import (
|
|||||||
|
|
||||||
|
|
||||||
def initialize(context):
|
def initialize(context):
|
||||||
context.ASSET_NAME = 'BTC_USDT'
|
context.ASSET_NAME = 'btc_usdt'
|
||||||
context.TARGET_HODL_RATIO = 0.8
|
context.TARGET_HODL_RATIO = 0.8
|
||||||
context.RESERVE_RATIO = 1.0 - context.TARGET_HODL_RATIO
|
context.RESERVE_RATIO = 1.0 - context.TARGET_HODL_RATIO
|
||||||
|
|
||||||
# For all trading pairs in the poloniex bundle, the default denomination
|
|
||||||
# currently supported by Catalyst is 1/1000th of a full coin. Use this
|
|
||||||
# constant to scale the price of up to that of a full coin if desired.
|
|
||||||
context.TICK_SIZE = 1000.0
|
|
||||||
|
|
||||||
context.is_buying = True
|
context.is_buying = True
|
||||||
context.asset = symbol(context.ASSET_NAME)
|
context.asset = symbol(context.ASSET_NAME)
|
||||||
|
|
||||||
@@ -91,7 +85,7 @@ def analyze(context=None, results=None):
|
|||||||
|
|
||||||
ax2 = plt.subplot(612, sharex=ax1)
|
ax2 = plt.subplot(612, sharex=ax1)
|
||||||
ax2.set_ylabel('{asset} (USD)'.format(asset=context.ASSET_NAME))
|
ax2.set_ylabel('{asset} (USD)'.format(asset=context.ASSET_NAME))
|
||||||
(context.TICK_SIZE * results[['price']]).plot(ax=ax2)
|
results[['price']].plot(ax=ax2)
|
||||||
|
|
||||||
trans = results.ix[[t != [] for t in results.transactions]]
|
trans = results.ix[[t != [] for t in results.transactions]]
|
||||||
buys = trans.ix[
|
buys = trans.ix[
|
||||||
@@ -99,7 +93,7 @@ def analyze(context=None, results=None):
|
|||||||
]
|
]
|
||||||
ax2.plot(
|
ax2.plot(
|
||||||
buys.index,
|
buys.index,
|
||||||
context.TICK_SIZE * results.price[buys.index],
|
results.price[buys.index],
|
||||||
'^',
|
'^',
|
||||||
markersize=10,
|
markersize=10,
|
||||||
color='g',
|
color='g',
|
||||||
@@ -141,15 +135,3 @@ def analyze(context=None, results=None):
|
|||||||
plt.gcf().set_size_inches(18, 8)
|
plt.gcf().set_size_inches(18, 8)
|
||||||
plt.show()
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
run_algorithm(
|
|
||||||
capital_base=10000,
|
|
||||||
data_frequency='minute',
|
|
||||||
initialize=initialize,
|
|
||||||
handle_data=handle_data,
|
|
||||||
analyze=analyze,
|
|
||||||
exchange_name='poloniex',
|
|
||||||
base_currency='usd',
|
|
||||||
start=pd.to_datetime('2017-10-1', utc=True),
|
|
||||||
end=pd.to_datetime('2017-11-10', utc=True),
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -0,0 +1,172 @@
|
|||||||
|
|
|
||||||
|
Example Algorithms
|
||||||
|
==================
|
||||||
|
|
||||||
|
This section documents a small number of example algorithms to complement the
|
||||||
|
beginner tutorial, and show how other trading algorithms can be implemented
|
||||||
|
using Catalyst:
|
||||||
|
|
||||||
|
Buy and Hodl
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
source: `examples/buy_and_hodl.py <https://github.com/enigmampc/catalyst/blob/master/catalyst/examples/buy_and_hodl.py>`_
|
||||||
|
|
||||||
|
First ingest the historical pricing data needed to run this algorithm:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
catalyst ingest-exchange -x poloniex -f daily -i btc_usdt
|
||||||
|
|
||||||
|
Then, you can run the code below with the following command:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
catalyst run -f buy_and_hodl.py --start 2015-3-1 --end 2017-10-31 --capital-base 100000 -x poloniex -c btc -o bah.pickle
|
||||||
|
|
||||||
|
This command will run the trading algorithm in the specified time range and
|
||||||
|
plot the resulting performance using the matplotlib library. You can choose any
|
||||||
|
date interval with the ``--start`` and ``--end`` parameters, but bear in mind
|
||||||
|
that 2015-3-1 is the earliest date that Catalyst supports (if you choose an
|
||||||
|
earlier date, you'll get an error), and the most recent date you can choose is
|
||||||
|
one day prior to the current date.
|
||||||
|
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Copyright 2017 Enigma MPC, Inc.
|
||||||
|
# Copyright 2015 Quantopian, Inc.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
import pandas as pd
|
||||||
|
|
||||||
|
from catalyst.api import (
|
||||||
|
order_target_value,
|
||||||
|
symbol,
|
||||||
|
record,
|
||||||
|
cancel_order,
|
||||||
|
get_open_orders,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def initialize(context):
|
||||||
|
context.ASSET_NAME = 'btc_usdt'
|
||||||
|
context.TARGET_HODL_RATIO = 0.8
|
||||||
|
context.RESERVE_RATIO = 1.0 - context.TARGET_HODL_RATIO
|
||||||
|
|
||||||
|
context.is_buying = True
|
||||||
|
context.asset = symbol(context.ASSET_NAME)
|
||||||
|
|
||||||
|
context.i = 0
|
||||||
|
|
||||||
|
|
||||||
|
def handle_data(context, data):
|
||||||
|
context.i += 1
|
||||||
|
|
||||||
|
starting_cash = context.portfolio.starting_cash
|
||||||
|
target_hodl_value = context.TARGET_HODL_RATIO * starting_cash
|
||||||
|
reserve_value = context.RESERVE_RATIO * starting_cash
|
||||||
|
|
||||||
|
# Cancel any outstanding orders
|
||||||
|
orders = get_open_orders(context.asset) or []
|
||||||
|
for order in orders:
|
||||||
|
cancel_order(order)
|
||||||
|
|
||||||
|
# Stop buying after passing the reserve threshold
|
||||||
|
cash = context.portfolio.cash
|
||||||
|
if cash <= reserve_value:
|
||||||
|
context.is_buying = False
|
||||||
|
|
||||||
|
# Retrieve current asset price from pricing data
|
||||||
|
price = data.current(context.asset, 'price')
|
||||||
|
|
||||||
|
# Check if still buying and could (approximately) afford another purchase
|
||||||
|
if context.is_buying and cash > price:
|
||||||
|
# Place order to make position in asset equal to target_hodl_value
|
||||||
|
order_target_value(
|
||||||
|
context.asset,
|
||||||
|
target_hodl_value,
|
||||||
|
limit_price=price * 1.1,
|
||||||
|
stop_price=price * 0.9,
|
||||||
|
)
|
||||||
|
|
||||||
|
record(
|
||||||
|
price=price,
|
||||||
|
volume=data.current(context.asset, 'volume'),
|
||||||
|
cash=cash,
|
||||||
|
starting_cash=context.portfolio.starting_cash,
|
||||||
|
leverage=context.account.leverage,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def analyze(context=None, results=None):
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
# Plot the portfolio and asset data.
|
||||||
|
ax1 = plt.subplot(611)
|
||||||
|
results[['portfolio_value']].plot(ax=ax1)
|
||||||
|
ax1.set_ylabel('Portfolio Value (USD)')
|
||||||
|
|
||||||
|
ax2 = plt.subplot(612, sharex=ax1)
|
||||||
|
ax2.set_ylabel('{asset} (USD)'.format(asset=context.ASSET_NAME))
|
||||||
|
results[['price']].plot(ax=ax2)
|
||||||
|
|
||||||
|
trans = results.ix[[t != [] for t in results.transactions]]
|
||||||
|
buys = trans.ix[
|
||||||
|
[t[0]['amount'] > 0 for t in trans.transactions]
|
||||||
|
]
|
||||||
|
ax2.plot(
|
||||||
|
buys.index,
|
||||||
|
results.price[buys.index],
|
||||||
|
'^',
|
||||||
|
markersize=10,
|
||||||
|
color='g',
|
||||||
|
)
|
||||||
|
|
||||||
|
ax3 = plt.subplot(613, sharex=ax1)
|
||||||
|
results[['leverage', 'alpha', 'beta']].plot(ax=ax3)
|
||||||
|
ax3.set_ylabel('Leverage ')
|
||||||
|
|
||||||
|
ax4 = plt.subplot(614, sharex=ax1)
|
||||||
|
results[['starting_cash', 'cash']].plot(ax=ax4)
|
||||||
|
ax4.set_ylabel('Cash (USD)')
|
||||||
|
|
||||||
|
results[[
|
||||||
|
'treasury',
|
||||||
|
'algorithm',
|
||||||
|
'benchmark',
|
||||||
|
]] = results[[
|
||||||
|
'treasury_period_return',
|
||||||
|
'algorithm_period_return',
|
||||||
|
'benchmark_period_return',
|
||||||
|
]]
|
||||||
|
|
||||||
|
ax5 = plt.subplot(615, sharex=ax1)
|
||||||
|
results[[
|
||||||
|
'treasury',
|
||||||
|
'algorithm',
|
||||||
|
'benchmark',
|
||||||
|
]].plot(ax=ax5)
|
||||||
|
ax5.set_ylabel('Percent Change')
|
||||||
|
|
||||||
|
ax6 = plt.subplot(616, sharex=ax1)
|
||||||
|
results[['volume']].plot(ax=ax6)
|
||||||
|
ax6.set_ylabel('Volume (mCoins/5min)')
|
||||||
|
|
||||||
|
plt.legend(loc=3)
|
||||||
|
|
||||||
|
# Show the plot.
|
||||||
|
plt.gcf().set_size_inches(18, 8)
|
||||||
|
plt.show()
|
||||||
|
|
||||||
@@ -12,6 +12,8 @@ Table of Contents
|
|||||||
jupyter
|
jupyter
|
||||||
live-trading
|
live-trading
|
||||||
naming-convention
|
naming-convention
|
||||||
|
example-algos
|
||||||
|
utilities
|
||||||
videos
|
videos
|
||||||
resources
|
resources
|
||||||
development-guidelines
|
development-guidelines
|
||||||
|
|||||||
@@ -0,0 +1,149 @@
|
|||||||
|
Utilities
|
||||||
|
=========
|
||||||
|
|
||||||
|
This section covers a variety of utilites that provide complimentary
|
||||||
|
functionality to your trading algorithms. These are code snippets that you can
|
||||||
|
add to any algorithm to add the desired functionality.
|
||||||
|
|
||||||
|
If you are looking for example trading algorithms, see the corresponding section.
|
||||||
|
|
||||||
|
Output to CSV file
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Add this script to the analyze method to create and save a CSV file with the
|
||||||
|
results from the trading algorithm. This file will include the default
|
||||||
|
parameters of the results DataFrame plus any recorded variables and will be
|
||||||
|
saved in the same location where your trading algorithm is saved. The exact
|
||||||
|
script that you need to use depends on the interface that you are using to run
|
||||||
|
your trading algorithm, which could be the CLI or a Python Interpreter.
|
||||||
|
|
||||||
|
1. Script to use with CLI:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
def analyze(context=None, results=None):
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
from os.path import basename
|
||||||
|
|
||||||
|
# Save results in CSV file
|
||||||
|
filename = os.path.splitext(basename(sys.argv[3]))[0]
|
||||||
|
results.to_csv(filename + '.csv')
|
||||||
|
|
||||||
|
2. Script to use with Python Interpreter:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
def analyze(context=None, results=None):
|
||||||
|
import os
|
||||||
|
from os.path import basename
|
||||||
|
|
||||||
|
# Save results in CSV file
|
||||||
|
filename = os.path.splitext(os.path.basename(__file__))[0]
|
||||||
|
results.to_csv(filename + '.csv')
|
||||||
|
|
||||||
|
Extracting market data
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Use this script to save the price and volume data of one cryptoasset in a CSV
|
||||||
|
file, which will be saved in the same location and with the same name as your
|
||||||
|
Python file. To get custom data, simply modify the asset's symbol and the dates.
|
||||||
|
Run this script directly from your development environment: python scriptname.py,
|
||||||
|
where the contents of 'scriptname.py' are as follows. Two different version are
|
||||||
|
provided as an example for daily- and minute-resolution data respectively:
|
||||||
|
|
||||||
|
Simpler case for daily data
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import os
|
||||||
|
import pytz
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from catalyst.api import record, symbol, symbols
|
||||||
|
from catalyst.utils.run_algo import run_algorithm
|
||||||
|
|
||||||
|
def initialize(context):
|
||||||
|
# Portfolio assets list
|
||||||
|
context.asset = symbol('btc_usdt') # Bitcoin on Poloniex
|
||||||
|
|
||||||
|
def handle_data(context, data):
|
||||||
|
# Variables to record for a given asset: price and volume
|
||||||
|
price = data.current(context.asset, 'price')
|
||||||
|
volume = data.current(context.asset, 'volume')
|
||||||
|
record(price=price, volume=volume)
|
||||||
|
|
||||||
|
def analyze(context=None, results=None):
|
||||||
|
|
||||||
|
# Generate DataFrame with Price and Volume only
|
||||||
|
data = results[['price','volume']]
|
||||||
|
|
||||||
|
# Save results in CSV file
|
||||||
|
filename = os.path.splitext(os.path.basename(__file__))[0]
|
||||||
|
data.to_csv(filename + '.csv')
|
||||||
|
|
||||||
|
''' Bitcoin data is available on Poloniex since 2015-3-1.
|
||||||
|
Dates vary for other tokens. In the example below, we choose the
|
||||||
|
full month of July of 2017.
|
||||||
|
'''
|
||||||
|
start = datetime(2017, 1, 1, 0, 0, 0, 0, pytz.utc)
|
||||||
|
end = datetime(2017, 7, 31, 0, 0, 0, 0, pytz.utc)
|
||||||
|
results = run_algorithm(initialize=initialize,
|
||||||
|
handle_data=handle_data,
|
||||||
|
analyze=analyze,
|
||||||
|
start=start,
|
||||||
|
end=end,
|
||||||
|
exchange_name='poloniex',
|
||||||
|
capital_base=10000,
|
||||||
|
base_currency = 'usdt')
|
||||||
|
|
||||||
|
More versatile case for minute data
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import os
|
||||||
|
import csv
|
||||||
|
import pytz
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from catalyst.api import record, symbol, symbols
|
||||||
|
from catalyst.utils.run_algo import run_algorithm
|
||||||
|
|
||||||
|
|
||||||
|
def initialize(context):
|
||||||
|
# Portfolio assets list
|
||||||
|
context.asset = symbol('btc_usdt') # Bitcoin on Poloniex
|
||||||
|
|
||||||
|
# Creates a .CSV file with the same name as this script to store results
|
||||||
|
context.csvfile = open(os.path.splitext(
|
||||||
|
os.path.basename(__file__))[0]+'.csv', 'w+')
|
||||||
|
context.csvwriter = csv.writer(context.csvfile)
|
||||||
|
|
||||||
|
def handle_data(context, data):
|
||||||
|
# Variables to record for a given asset: price and volume
|
||||||
|
# Other options include 'open', 'high', 'open', 'close'
|
||||||
|
# Please note that 'price' equals 'close'
|
||||||
|
date = context.blotter.current_dt # current time in each iteration
|
||||||
|
price = data.current(context.asset, 'price')
|
||||||
|
volume = data.current(context.asset, 'volume')
|
||||||
|
|
||||||
|
# Writes one line to CSV on each iteration with the chosen variables
|
||||||
|
context.csvwriter.writerow([date,price,volume])
|
||||||
|
|
||||||
|
def analyze(context=None, results=None):
|
||||||
|
# Close open file properly at the end
|
||||||
|
context.csvfile.close()
|
||||||
|
|
||||||
|
|
||||||
|
# Bitcoin data is available from 2015-3-2. Dates vary for other tokens.
|
||||||
|
start = datetime(2017, 7, 30, 0, 0, 0, 0, pytz.utc)
|
||||||
|
end = datetime(2017, 7, 31, 0, 0, 0, 0, pytz.utc)
|
||||||
|
results = run_algorithm(initialize=initialize,
|
||||||
|
handle_data=handle_data,
|
||||||
|
analyze=analyze,
|
||||||
|
start=start,
|
||||||
|
end=end,
|
||||||
|
exchange_name='poloniex',
|
||||||
|
data_frequency='minute',
|
||||||
|
base_currency ='usdt',
|
||||||
|
capital_base=10000 )
|
||||||
Reference in New Issue
Block a user