mirror of
https://github.com/wassname/catalyst.git
synced 2026-07-10 03:28:37 +08:00
172 lines
6.9 KiB
Python
172 lines
6.9 KiB
Python
"""
|
|
Requires Catalyst version 0.3.0 or above
|
|
Tested on Catalyst version 0.3.3
|
|
|
|
This example aims to provide an easy way for users to learn how to
|
|
collect data from any given exchange and select a subset of the available
|
|
currency pairs for trading. You simply need to specify the exchange and
|
|
the market (base_currency) that you want to focus on. You will then see
|
|
how to create a universe of assets, and filter it based the market you
|
|
desire.
|
|
|
|
The example prints out the closing price of all the pairs for a given
|
|
market in a given exchange every 30 minutes. The example also contains
|
|
the OHLCV data with minute-resolution for the past seven days which
|
|
could be used to create indicators. Use this code as the backbone to
|
|
create your own trading strategy.
|
|
|
|
The lookback_date variable is used to ensure data for a coin existed on
|
|
the lookback period specified.
|
|
|
|
To run, execute the following two commands in a terminal (inside catalyst
|
|
environment). The first one retrieves all the pricing data needed for this
|
|
script to run (only needs to be run once), and the second one executes this
|
|
script with the parameters specified in the run_algorithm() call at the end
|
|
of the file:
|
|
|
|
catalyst ingest-exchange -x bitfinex -f minute
|
|
|
|
python simple_universe.py
|
|
|
|
"""
|
|
from datetime import timedelta
|
|
|
|
import numpy as np
|
|
import pandas as pd
|
|
|
|
from catalyst import run_algorithm
|
|
from catalyst.api import (symbols, )
|
|
from catalyst.exchange.utils.exchange_utils import get_exchange_symbols
|
|
|
|
|
|
def initialize(context):
|
|
context.i = -1 # minute counter
|
|
context.exchange = list(context.exchanges.values())[0].name.lower()
|
|
context.base_currency = list(context.exchanges.values())[0].base_currency.lower()
|
|
|
|
|
|
def handle_data(context, data):
|
|
context.i += 1
|
|
lookback_days = 7 # 7 days
|
|
|
|
# current date & time in each iteration formatted into a string
|
|
now = data.current_dt
|
|
date, time = now.strftime('%Y-%m-%d %H:%M:%S').split(' ')
|
|
lookback_date = now - timedelta(days=lookback_days)
|
|
# keep only the date as a string, discard the time
|
|
lookback_date = lookback_date.strftime('%Y-%m-%d %H:%M:%S').split(' ')[0]
|
|
|
|
one_day_in_minutes = 1440 # 60 * 24 assumes data_frequency='minute'
|
|
# update universe everyday at midnight
|
|
if not context.i % one_day_in_minutes:
|
|
context.universe = universe(context, lookback_date, date)
|
|
|
|
# get data every 30 minutes
|
|
minutes = 30
|
|
|
|
# get lookback_days of history data: that is 'lookback' number of bins
|
|
lookback = int(one_day_in_minutes / minutes * lookback_days)
|
|
if not context.i % minutes and context.universe:
|
|
# we iterate for every pair in the current universe
|
|
for coin in context.coins:
|
|
pair = str(coin.symbol)
|
|
|
|
# Get 30 minute interval OHLCV data. This is the standard data
|
|
# required for candlestick or indicators/signals. Return Pandas
|
|
# DataFrames. 30T means 30-minute re-sampling of one minute data.
|
|
# Adjust it to your desired time interval as needed.
|
|
opened = fill(data.history(coin,
|
|
'open',
|
|
bar_count=lookback,
|
|
frequency='30T')).values
|
|
high = fill(data.history(coin,
|
|
'high',
|
|
bar_count=lookback,
|
|
frequency='30T')).values
|
|
low = fill(data.history(coin,
|
|
'low',
|
|
bar_count=lookback,
|
|
frequency='30T')).values
|
|
close = fill(data.history(coin,
|
|
'price',
|
|
bar_count=lookback,
|
|
frequency='30T')).values
|
|
volume = fill(data.history(coin,
|
|
'volume',
|
|
bar_count=lookback,
|
|
frequency='30T')).values
|
|
|
|
# close[-1] is the last value in the set, which is the equivalent
|
|
# to current price (as in the most recent value)
|
|
# displays the minute price for each pair every 30 minutes
|
|
print('{now}: {pair} -\tO:{o},\tH:{h},\tL:{c},\tC{c},'
|
|
'\tV:{v}'.format(
|
|
now=now,
|
|
pair=pair,
|
|
o=opened[-1],
|
|
h=high[-1],
|
|
l=low[-1],
|
|
c=close[-1],
|
|
v=volume[-1],
|
|
))
|
|
|
|
# -------------------------------------------------------------
|
|
# --------------- Insert Your Strategy Here -------------------
|
|
# -------------------------------------------------------------
|
|
|
|
|
|
def analyze(context=None, results=None):
|
|
pass
|
|
|
|
|
|
# Get the universe for a given exchange and a given base_currency market
|
|
# Example: Poloniex BTC Market
|
|
def universe(context, lookback_date, current_date):
|
|
# get all the pairs for the given exchange
|
|
json_symbols = get_exchange_symbols(context.exchange)
|
|
# convert into a DataFrame for easier processing
|
|
df = pd.DataFrame.from_dict(json_symbols).transpose().astype(str)
|
|
df['base_currency'] = df.apply(lambda row: row.symbol.split('_')[1],
|
|
axis=1)
|
|
df['market_currency'] = df.apply(lambda row: row.symbol.split('_')[0],
|
|
axis=1)
|
|
|
|
# Filter all the pairs to get only the ones for a given base_currency
|
|
df = df[df['base_currency'] == context.base_currency]
|
|
|
|
# Filter all pairs to ensure that pair existed in the current date range
|
|
df = df[df.start_date < lookback_date]
|
|
df = df[df.end_daily >= current_date]
|
|
context.coins = symbols(*df.symbol) # convert all the pairs to symbols
|
|
|
|
return df.symbol.tolist()
|
|
|
|
|
|
# Replace all NA, NAN or infinite values with its nearest value
|
|
def fill(series):
|
|
if isinstance(series, pd.Series):
|
|
return series.replace([np.inf, -np.inf], np.nan).ffill().bfill()
|
|
elif isinstance(series, np.ndarray):
|
|
return pd.Series(series).replace(
|
|
[np.inf, -np.inf], np.nan
|
|
).ffill().bfill().values
|
|
else:
|
|
return series
|
|
|
|
|
|
if __name__ == '__main__':
|
|
start_date = pd.to_datetime('2017-11-10', utc=True)
|
|
end_date = pd.to_datetime('2017-11-13', utc=True)
|
|
|
|
performance = run_algorithm(start=start_date, end=end_date,
|
|
capital_base=100.0, # amount of base_currency
|
|
initialize=initialize,
|
|
handle_data=handle_data,
|
|
analyze=analyze,
|
|
exchange_name='poloniex',
|
|
data_frequency='minute',
|
|
base_currency='btc',
|
|
live=False,
|
|
live_graph=False,
|
|
algo_namespace='simple_universe')
|