Fixed an issue with data.history more recent than the server

This commit is contained in:
fredfortier
2017-10-19 15:24:00 -04:00
parent 1a97111ceb
commit 619eb3cfa4
4 changed files with 194 additions and 35 deletions
+156
View File
@@ -0,0 +1,156 @@
import talib
from logbook import Logger
from catalyst.api import (
order,
order_target_percent,
symbol,
record,
get_open_orders,
)
from catalyst.exchange.stats_utils import get_pretty_stats
from catalyst.utils.run_algo import run_algorithm
algo_namespace = 'buy_the_dip_live'
log = Logger('buy low sell high')
def initialize(context):
log.info('initializing algo')
context.ASSET_NAME = 'XRP_BTC'
context.asset = symbol(context.ASSET_NAME)
context.TARGET_POSITIONS = 300
context.PROFIT_TARGET = 0.1
context.SLIPPAGE_ALLOWED = 0.02
context.retry_check_open_orders = 10
context.retry_update_portfolio = 10
context.retry_order = 5
context.errors = []
pass
def _handle_data(context, data):
prices = data.history(
context.asset,
fields='price',
bar_count=20,
frequency='15m'
)
rsi = talib.RSI(prices.values, timeperiod=14)[-1]
log.info('got rsi: {}'.format(rsi))
# Buying more when RSI is low, this should lower our cost basis
if rsi <= 30:
buy_increment = 50
elif rsi <= 40:
buy_increment = 20
# elif rsi <= 70:
# buy_increment = 5
else:
buy_increment = None
cash = context.portfolio.cash
log.info('base currency available: {cash}'.format(cash=cash))
price = data.current(context.asset, 'price')
log.info('got price {price}'.format(price=price))
record(
price=price,
rsi=rsi,
)
orders = get_open_orders(context.asset)
if orders:
log.info('skipping bar until all open orders execute')
return
is_buy = False
cost_basis = None
if context.asset in context.portfolio.positions:
position = context.portfolio.positions[context.asset]
cost_basis = position.cost_basis
log.info(
'found {amount} positions with cost basis {cost_basis}'.format(
amount=position.amount,
cost_basis=cost_basis
)
)
if position.amount >= context.TARGET_POSITIONS:
log.info('reached positions target: {}'.format(position.amount))
return
if price < cost_basis:
is_buy = True
elif position.amount > 0 and \
price > cost_basis * (1 + context.PROFIT_TARGET):
profit = (price * position.amount) - (cost_basis * position.amount)
log.info('closing position, taking profit: {}'.format(profit))
order_target_percent(
asset=context.asset,
target=0,
limit_price=price * (1 - context.SLIPPAGE_ALLOWED),
)
else:
log.info('no buy or sell opportunity found')
else:
is_buy = True
if is_buy:
if buy_increment is None:
log.info('the rsi is too high to consider buying {}'.format(rsi))
return
if price * buy_increment > cash:
log.info('not enough base currency to consider buying')
return
log.info(
'buying position cheaper than cost basis {} < {}'.format(
price,
cost_basis
)
)
order(
asset=context.asset,
amount=buy_increment,
limit_price=price * (1 + context.SLIPPAGE_ALLOWED)
)
def handle_data(context, data):
log.info('handling bar {}'.format(data.current_dt))
# try:
_handle_data(context, data)
# except Exception as e:
# log.warn('aborting the bar on error {}'.format(e))
# context.errors.append(e)
log.info('completed bar {}, total execution errors {}'.format(
data.current_dt,
len(context.errors)
))
if len(context.errors) > 0:
log.info('the errors:\n{}'.format(context.errors))
def analyze(context, stats):
log.info('the daily stats:\n{}'.format(get_pretty_stats(stats)))
pass
run_algorithm(
initialize=initialize,
handle_data=handle_data,
analyze=analyze,
exchange_name='bitfinex',
live=True,
algo_namespace=algo_namespace,
base_currency='btc'
)
+1 -9
View File
@@ -134,21 +134,13 @@ def get_adj_dates(start, end, assets, data_frequency):
if end is None or (last_entry is not None and end > last_entry):
end = last_entry
if end is None:
if end is None or start >= end:
raise NoDataAvailableOnExchange(
exchange=asset.exchange.title(),
symbol=[asset.symbol.encode('utf-8')],
data_frequency=data_frequency,
)
if end is None or start >= end:
raise PricingDataBeforeTradingError(
symbols=[asset.symbol.encode('utf-8')],
exchange=asset.exchange.title(),
first_trading_day=earliest_trade,
dt=end
)
return start, end
+35 -24
View File
@@ -16,7 +16,7 @@ from catalyst.exchange.exchange_bundle import ExchangeBundle
from catalyst.exchange.exchange_errors import MismatchingBaseCurrencies, \
InvalidOrderStyle, BaseCurrencyNotFoundError, SymbolNotFoundOnExchange, \
InvalidHistoryFrequencyError, MismatchingFrequencyError, \
BundleNotFoundError
BundleNotFoundError, NoDataAvailableOnExchange
from catalyst.exchange.exchange_execution import ExchangeStopLimitOrder, \
ExchangeLimitOrder, ExchangeStopOrder
from catalyst.exchange.exchange_portfolio import ExchangePortfolio
@@ -487,11 +487,13 @@ class Exchange:
data_frequency = 'daily'
elif unit.lower() == 'm':
if data_frequency != 'minute':
raise MismatchingFrequencyError(
frequency=frequency,
data_frequency=data_frequency
)
# if data_frequency != 'minute':
# raise MismatchingFrequencyError(
# frequency=frequency,
# data_frequency=data_frequency
# )
if data_frequency == 'daily':
data_frequency = 'minute'
else:
raise InvalidHistoryFrequencyError(frequency)
@@ -499,32 +501,41 @@ class Exchange:
adj_bar_count = candle_size * bar_count
start_dt = get_start_dt(end_dt, adj_bar_count, data_frequency)
adj_start_dt, adj_end_dt = get_adj_dates(
start_dt, end_dt, assets, data_frequency
)
try:
adj_start_dt, adj_end_dt = get_adj_dates(
start_dt, end_dt, assets, data_frequency
)
in_bundle = True
missing_assets = self.bundle.filter_existing_assets(
assets=assets,
start_dt=adj_start_dt,
end_dt=adj_end_dt,
data_frequency=data_frequency
)
except NoDataAvailableOnExchange:
in_bundle = False
if missing_assets:
self.bundle.ingest_assets(
if in_bundle:
missing_assets = self.bundle.filter_existing_assets(
assets=assets,
start_dt=adj_start_dt,
end_dt=adj_end_dt,
data_frequency=data_frequency
)
series = self.get_series_from_bundle(
assets=assets,
start_dt=adj_start_dt,
end_dt=adj_end_dt,
data_frequency=data_frequency,
field=field
)
if missing_assets:
self.bundle.ingest_assets(
assets=assets,
start_dt=adj_start_dt,
end_dt=adj_end_dt,
data_frequency=data_frequency
)
series = self.get_series_from_bundle(
assets=assets,
start_dt=adj_start_dt,
end_dt=adj_end_dt,
data_frequency=data_frequency,
field=field
)
else:
series = dict()
for asset in assets:
if asset not in series or series[asset].index[-1] < end_dt:
+2 -2
View File
@@ -15,7 +15,7 @@ from catalyst.exchange.exchange_bcolz import BcolzExchangeBarReader, \
BcolzExchangeBarWriter
from catalyst.exchange.exchange_errors import EmptyValuesInBundleError, \
InvalidHistoryFrequencyError, PricingDataBeforeTradingError, \
TempBundleNotFoundError
TempBundleNotFoundError, NoDataAvailableOnExchange
from catalyst.exchange.exchange_utils import get_exchange_folder
from catalyst.utils.cli import maybe_show_progress
from catalyst.utils.paths import ensure_directory
@@ -316,7 +316,7 @@ class ExchangeBundle:
asset_start, asset_end = \
get_adj_dates(start_dt, end_dt, [asset], data_frequency)
except PricingDataBeforeTradingError:
except NoDataAvailableOnExchange:
continue
# Aligning start / end dates with the daily calendar