mirror of
https://github.com/wassname/catalyst.git
synced 2026-07-22 12:40:30 +08:00
Compare commits
8
Commits
live-trading
...
0.1.dev9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
49bfd32341 | ||
|
|
01473e5146 | ||
|
|
16f9ab3ba5 | ||
|
|
3a44a3cc1f | ||
|
|
24fd0fa6f8 | ||
|
|
b2e5b5f73d | ||
|
|
0ef8b341ca | ||
|
|
753ca1db5a |
@@ -42,8 +42,7 @@ class PoloniexBundle(BaseCryptoPricingBundle):
|
|||||||
@lazyval
|
@lazyval
|
||||||
def tar_url(self):
|
def tar_url(self):
|
||||||
return (
|
return (
|
||||||
'https://www.dropbox.com/s/9naqffawnq8o4r2/'
|
'https://s3.amazonaws.com/enigmaco/catalyst-bundles/poloniex/poloniex-bundle.tar.gz'
|
||||||
'poloniex-bundle.tar?dl=1'
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@lazyval
|
@lazyval
|
||||||
@@ -103,7 +102,10 @@ class PoloniexBundle(BaseCryptoPricingBundle):
|
|||||||
)
|
)
|
||||||
raw.set_index('date', inplace=True)
|
raw.set_index('date', inplace=True)
|
||||||
|
|
||||||
scale = 1
|
# BcolzDailyBarReader introduces a 1/1000 factor in the way pricing is stored
|
||||||
|
# on disk, which we compensate here to get the right pricing amounts
|
||||||
|
# ref: data/us_equity_pricing.py
|
||||||
|
scale = 1000
|
||||||
raw.loc[:, 'open'] /= scale
|
raw.loc[:, 'open'] /= scale
|
||||||
raw.loc[:, 'high'] /= scale
|
raw.loc[:, 'high'] /= scale
|
||||||
raw.loc[:, 'low'] /= scale
|
raw.loc[:, 'low'] /= scale
|
||||||
@@ -164,4 +166,4 @@ register_bundle(PoloniexBundle, ['USDT_BTC',])
|
|||||||
For a production environment make sure to use (to bundle all pairs):
|
For a production environment make sure to use (to bundle all pairs):
|
||||||
register_bundle(PoloniexBundle)
|
register_bundle(PoloniexBundle)
|
||||||
'''
|
'''
|
||||||
register_bundle(PoloniexBundle)
|
register_bundle(PoloniexBundle, create_writers=False)
|
||||||
|
|||||||
+64
-31
@@ -96,16 +96,15 @@ def has_data_for_dates(series_or_df, first_date, last_date):
|
|||||||
first, last = dts[[0, -1]].tz_localize(None)
|
first, last = dts[[0, -1]].tz_localize(None)
|
||||||
return (first <= first_date.tz_localize(None)) and (last >= last_date.tz_localize(None))
|
return (first <= first_date.tz_localize(None)) and (last >= last_date.tz_localize(None))
|
||||||
|
|
||||||
def load_crypto_market_data(trading_day=None,
|
def load_crypto_market_data(trading_day=None, trading_days=None, bm_symbol='USDT_BTC',
|
||||||
trading_days=None,
|
bundle=None, bundle_data=None, environ=None):
|
||||||
bm_symbol='USDT_BTC',
|
|
||||||
environ=None):
|
|
||||||
if trading_day is None:
|
if trading_day is None:
|
||||||
trading_day = get_calendar('OPEN').trading_day
|
trading_day = get_calendar('OPEN').trading_day
|
||||||
if trading_days is None:
|
if trading_days is None:
|
||||||
trading_days = get_calendar('OPEN').all_sessions
|
trading_days = get_calendar('OPEN').all_sessions
|
||||||
|
|
||||||
first_date = trading_days[0]
|
first_date = trading_days[1]
|
||||||
now = pd.Timestamp.utcnow()
|
now = pd.Timestamp.utcnow()
|
||||||
|
|
||||||
# We expect to have benchmark and treasury data that's current up until
|
# We expect to have benchmark and treasury data that's current up until
|
||||||
@@ -122,7 +121,14 @@ def load_crypto_market_data(trading_day=None,
|
|||||||
|
|
||||||
# We'll attempt to download new data if the latest entry in our cache is
|
# We'll attempt to download new data if the latest entry in our cache is
|
||||||
# before this date.
|
# before this date.
|
||||||
last_date = trading_days[trading_days.get_loc(now, method='ffill') - 2]
|
if(bundle_data):
|
||||||
|
# If we are using the bundle to retrieve the cryptobenchmark, find the last
|
||||||
|
# date for which there is trading data in the bundle
|
||||||
|
asset = bundle_data.asset_finder.lookup_symbol(symbol=bm_symbol,as_of_date=None)
|
||||||
|
ix = bundle_data.daily_bar_reader._last_rows[asset.sid]
|
||||||
|
last_date = pd.to_datetime(bundle_data.daily_bar_reader._spot_col('day')[ix],unit='s')
|
||||||
|
else:
|
||||||
|
last_date = trading_days[trading_days.get_loc(now, method='ffill') - 2]
|
||||||
|
|
||||||
br = ensure_crypto_benchmark_data(
|
br = ensure_crypto_benchmark_data(
|
||||||
bm_symbol,
|
bm_symbol,
|
||||||
@@ -132,11 +138,13 @@ def load_crypto_market_data(trading_day=None,
|
|||||||
# We need the trading_day to figure out the close prior to the first
|
# We need the trading_day to figure out the close prior to the first
|
||||||
# date so that we can compute returns for the first date.
|
# date so that we can compute returns for the first date.
|
||||||
trading_day,
|
trading_day,
|
||||||
|
bundle,
|
||||||
|
bundle_data,
|
||||||
environ,
|
environ,
|
||||||
)
|
)
|
||||||
# Override first_date for treasury data since we have it for many more years
|
# Override first_date for treasury data since we have it for many more years
|
||||||
# and is independent of crypto data
|
# and is independent of crypto data
|
||||||
first_date_treasury = pd.Timestamp('1990-01-01', tz='UTC')
|
first_date_treasury = pd.Timestamp('1990-01-02', tz='UTC')
|
||||||
tc = ensure_treasury_data(
|
tc = ensure_treasury_data(
|
||||||
bm_symbol,
|
bm_symbol,
|
||||||
first_date_treasury,
|
first_date_treasury,
|
||||||
@@ -240,6 +248,8 @@ def ensure_crypto_benchmark_data(symbol,
|
|||||||
last_date,
|
last_date,
|
||||||
now,
|
now,
|
||||||
trading_day,
|
trading_day,
|
||||||
|
bundle,
|
||||||
|
bundle_data,
|
||||||
environ=None):
|
environ=None):
|
||||||
|
|
||||||
filename = get_benchmark_filename(symbol)
|
filename = get_benchmark_filename(symbol)
|
||||||
@@ -248,7 +258,7 @@ def ensure_crypto_benchmark_data(symbol,
|
|||||||
('Loading benchmark data for {symbol!r} '
|
('Loading benchmark data for {symbol!r} '
|
||||||
'from {first_date} to {last_date}'),
|
'from {first_date} to {last_date}'),
|
||||||
symbol=symbol,
|
symbol=symbol,
|
||||||
first_date=first_date - trading_day,
|
first_date=first_date,
|
||||||
last_date=last_date
|
last_date=last_date
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -261,34 +271,57 @@ def ensure_crypto_benchmark_data(symbol,
|
|||||||
environ,
|
environ,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if data is not None:
|
if data is not None:
|
||||||
return data
|
return data
|
||||||
|
|
||||||
# If no cached data was found or it was missing any dates then download the
|
# If no cached data was found or it was missing any dates then download the
|
||||||
# necessary data.
|
# necessary data.
|
||||||
logger.info(
|
|
||||||
('Downloading benchmark data for {symbol!r} '
|
|
||||||
'from {first_date} to {last_date}'),
|
|
||||||
symbol=symbol,
|
|
||||||
first_date=first_date - trading_day,
|
|
||||||
last_date=last_date
|
|
||||||
)
|
|
||||||
|
|
||||||
# Load benchmark symbol from Poloniex API
|
if(bundle == 'poloniex'):
|
||||||
try:
|
'''
|
||||||
bundle = PoloniexBundle()
|
If we're using the Poloniex bundle, we'll get the benchmark from the bundle
|
||||||
bench_raw = bundle._fetch_symbol_frame(
|
instead of downloading it from Poloniex every time we need it.
|
||||||
None,
|
Poloniex has a captcha for API queries originating from outside the US that
|
||||||
symbol,
|
prevents users abroad from getting Catalyst to work
|
||||||
get_calendar(bundle.calendar_name),
|
'''
|
||||||
first_date - trading_day,
|
logger.info(
|
||||||
last_date,
|
('Retrieving benchmark data from bundle for {symbol!r} from {first_date} to {last_date}'),
|
||||||
'daily',
|
symbol=symbol, first_date=first_date, last_date=last_date)
|
||||||
)
|
|
||||||
except (OSError, IOError, HTTPError):
|
asset = bundle_data.asset_finder.lookup_symbol(symbol=symbol,as_of_date=None)
|
||||||
logger.exception('Failed to fetch new crypto benchmark returns')
|
fields = ['day', 'close']
|
||||||
raise
|
raw = bundle_data.daily_bar_reader.load_raw_arrays(
|
||||||
|
columns=fields,
|
||||||
|
start_date=first_date - trading_day,
|
||||||
|
end_date=last_date,
|
||||||
|
assets=[asset,])
|
||||||
|
bench_raw = pd.concat([pd.DataFrame(raw[0], columns=['date']),pd.DataFrame(raw[1], columns=['close'])], axis=1)
|
||||||
|
bench_raw['date'] = pd.to_datetime(bench_raw['date'],unit='s')
|
||||||
|
bench_raw.set_index('date', inplace=True)
|
||||||
|
bench_raw.sort_index(inplace=True)
|
||||||
|
bench_raw = bench_raw[pd.to_datetime(first_date - trading_day):pd.to_datetime(last_date)]
|
||||||
|
|
||||||
|
else:
|
||||||
|
# This is how it used to be: downloading the benchmark everytime.
|
||||||
|
# Leaving this code here to be repurposed in the future for other bundles.
|
||||||
|
logger.info(
|
||||||
|
('Downloading benchmark data for {symbol!r} from {first_date} to {last_date}'),
|
||||||
|
symbol=symbol, first_date=first_date, last_date=last_date)
|
||||||
|
|
||||||
|
# Load benchmark symbol from Poloniex API
|
||||||
|
try:
|
||||||
|
bundle = PoloniexBundle()
|
||||||
|
bench_raw = bundle._fetch_symbol_frame(
|
||||||
|
None,
|
||||||
|
symbol,
|
||||||
|
get_calendar(bundle.calendar_name),
|
||||||
|
first_date - trading_day,
|
||||||
|
last_date,
|
||||||
|
'daily',
|
||||||
|
)
|
||||||
|
except (OSError, IOError, HTTPError):
|
||||||
|
logger.exception('Failed to fetch new crypto benchmark returns')
|
||||||
|
raise
|
||||||
|
|
||||||
# select close column and compute percent change between days
|
# select close column and compute percent change between days
|
||||||
daily_close = bench_raw[['close']]
|
daily_close = bench_raw[['close']]
|
||||||
@@ -518,7 +551,7 @@ def _load_cached_data(filename, first_date, last_date, now, resource_name,
|
|||||||
)
|
)
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
"Cache at {path} does not have data from {start} to {end}.\n",
|
"Cache at {path} does not have data from {start} to {end}.",
|
||||||
start=first_date,
|
start=first_date,
|
||||||
end=last_date,
|
end=last_date,
|
||||||
path=path,
|
path=path,
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ from catalyst.api import (
|
|||||||
get_open_orders,
|
get_open_orders,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def initialize(context):
|
def initialize(context):
|
||||||
context.ASSET_NAME = 'USDT_BTC'
|
context.ASSET_NAME = 'USDT_BTC'
|
||||||
context.TARGET_HODL_RATIO = 0.8
|
context.TARGET_HODL_RATIO = 0.8
|
||||||
@@ -42,8 +41,6 @@ def initialize(context):
|
|||||||
def handle_data(context, data):
|
def handle_data(context, data):
|
||||||
context.i += 1
|
context.i += 1
|
||||||
|
|
||||||
print 'i:', context.i
|
|
||||||
|
|
||||||
starting_cash = context.portfolio.starting_cash
|
starting_cash = context.portfolio.starting_cash
|
||||||
target_hodl_value = context.TARGET_HODL_RATIO * starting_cash
|
target_hodl_value = context.TARGET_HODL_RATIO * starting_cash
|
||||||
reserve_value = context.RESERVE_RATIO * starting_cash
|
reserve_value = context.RESERVE_RATIO * starting_cash
|
||||||
@@ -73,6 +70,7 @@ def handle_data(context, data):
|
|||||||
|
|
||||||
record(
|
record(
|
||||||
price=price,
|
price=price,
|
||||||
|
volume=data[context.asset].volume,
|
||||||
cash=cash,
|
cash=cash,
|
||||||
starting_cash=context.portfolio.starting_cash,
|
starting_cash=context.portfolio.starting_cash,
|
||||||
leverage=context.account.leverage,
|
leverage=context.account.leverage,
|
||||||
@@ -80,12 +78,13 @@ def handle_data(context, data):
|
|||||||
|
|
||||||
def analyze(context=None, results=None):
|
def analyze(context=None, results=None):
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
# Plot the portfolio and asset data.
|
# Plot the portfolio and asset data.
|
||||||
ax1 = plt.subplot(511)
|
ax1 = plt.subplot(611)
|
||||||
results[['portfolio_value']].plot(ax=ax1)
|
results[['portfolio_value']].plot(ax=ax1)
|
||||||
ax1.set_ylabel('Portfolio Value (USD)')
|
ax1.set_ylabel('Portfolio Value (USD)')
|
||||||
|
|
||||||
ax2 = plt.subplot(512, 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)
|
(context.TICK_SIZE * results[['price']]).plot(ax=ax2)
|
||||||
|
|
||||||
@@ -101,11 +100,11 @@ def analyze(context=None, results=None):
|
|||||||
color='g',
|
color='g',
|
||||||
)
|
)
|
||||||
|
|
||||||
ax3 = plt.subplot(513, sharex=ax1)
|
ax3 = plt.subplot(613, sharex=ax1)
|
||||||
results[['leverage', 'alpha', 'beta']].plot(ax=ax3)
|
results[['leverage', 'alpha', 'beta']].plot(ax=ax3)
|
||||||
ax3.set_ylabel('Leverage ')
|
ax3.set_ylabel('Leverage ')
|
||||||
|
|
||||||
ax4 = plt.subplot(514, sharex=ax1)
|
ax4 = plt.subplot(614, sharex=ax1)
|
||||||
results[['starting_cash', 'cash']].plot(ax=ax4)
|
results[['starting_cash', 'cash']].plot(ax=ax4)
|
||||||
ax4.set_ylabel('Cash (USD)')
|
ax4.set_ylabel('Cash (USD)')
|
||||||
|
|
||||||
@@ -119,7 +118,7 @@ def analyze(context=None, results=None):
|
|||||||
'benchmark_period_return',
|
'benchmark_period_return',
|
||||||
]]
|
]]
|
||||||
|
|
||||||
ax5 = plt.subplot(515, sharex=ax1)
|
ax5 = plt.subplot(615, sharex=ax1)
|
||||||
results[[
|
results[[
|
||||||
'treasury',
|
'treasury',
|
||||||
'algorithm',
|
'algorithm',
|
||||||
@@ -127,6 +126,10 @@ def analyze(context=None, results=None):
|
|||||||
]].plot(ax=ax5)
|
]].plot(ax=ax5)
|
||||||
ax5.set_ylabel('Percent Change')
|
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)
|
plt.legend(loc=3)
|
||||||
|
|
||||||
# Show the plot.
|
# Show the plot.
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ def _run(handle_data,
|
|||||||
open_calendar = get_calendar('OPEN')
|
open_calendar = get_calendar('OPEN')
|
||||||
|
|
||||||
env = TradingEnvironment(
|
env = TradingEnvironment(
|
||||||
load=partial(load_crypto_market_data, environ=environ),
|
load=partial(load_crypto_market_data, bundle=b, bundle_data=bundle_data, environ=environ),
|
||||||
bm_symbol='USDT_BTC',
|
bm_symbol='USDT_BTC',
|
||||||
trading_calendar=open_calendar,
|
trading_calendar=open_calendar,
|
||||||
asset_db_path=connstr,
|
asset_db_path=connstr,
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ def read_requirements(path,
|
|||||||
conda_format=False,
|
conda_format=False,
|
||||||
filter_names=None):
|
filter_names=None):
|
||||||
"""
|
"""
|
||||||
Read a requirements.txt file, expressed as a path relative to Zipline root.
|
Read a requirements.txt file, expressed as a path relative to Catalyst root.
|
||||||
|
|
||||||
Returns requirements with the pinned versions as lower bounds
|
Returns requirements with the pinned versions as lower bounds
|
||||||
if `strict_bounds` is falsey.
|
if `strict_bounds` is falsey.
|
||||||
|
|||||||
Reference in New Issue
Block a user