BLD: cleanup in algos and unit tests

This commit is contained in:
fredfortier
2017-11-04 14:46:09 -04:00
parent b636edb32f
commit 8c6ac53a05
5 changed files with 15 additions and 178 deletions
@@ -1,173 +0,0 @@
import talib
from logbook import Logger
import pandas as pd
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_low_sell_high_neo'
log = Logger(algo_namespace)
def initialize(context):
log.info('initializing algo')
context.asset = symbol('neo_btc', 'bitfinex')
context.TARGET_POSITIONS = 50000
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):
price = data.current(context.asset, 'close')
log.info('got price {price}'.format(price=price))
if price is None:
log.warn('no pricing data')
return
prices = data.history(
context.asset,
fields='price',
bar_count=1,
frequency='1m'
)
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 = 1
elif rsi <= 40:
buy_increment = 0.5
elif rsi <= 70:
buy_increment = 0.1
else:
buy_increment = None
cash = context.portfolio.cash
log.info('base currency available: {cash}'.format(cash=cash))
record(price=price)
orders = get_open_orders(context.asset)
if len(orders) > 0:
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:
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
)
)
limit_price = price * (1 + context.SLIPPAGE_ALLOWED)
order(
asset=context.asset,
amount=buy_increment,
limit_price=limit_price
)
pass
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',
# live_graph=False
# )
# Backtest
run_algorithm(
capital_base=250,
data_frequency='minute',
initialize=initialize,
handle_data=handle_data,
analyze=analyze,
exchange_name='bitfinex',
algo_namespace=algo_namespace,
base_currency='btc'
)
+1 -1
View File
@@ -31,7 +31,7 @@ def handle_data(context, data):
run_algorithm(
capital_base=250,
start=pd.to_datetime('2016-1-1', utc=True),
start=pd.to_datetime('2016-6-1', utc=True),
end=pd.to_datetime('2016-12-31', utc=True),
data_frequency='daily',
initialize=initialize,
+1 -1
View File
@@ -437,7 +437,7 @@ class ExchangeBundle:
if end is None or start is None or start >= end:
raise NoDataAvailableOnExchange(
exchange=[asset.exchange.name for asset in assets],
exchange=[asset.exchange for asset in assets],
symbol=[asset.symbol for asset in assets],
data_frequency=data_frequency,
)
+9
View File
@@ -2,6 +2,15 @@
Release Notes
=============
Version 0.3.5
^^^^^^^^^^^^^
**Release Date**: 2017-11-2
Bug Fixes
~~~~~~~~~
- Added workaround for: KeyError: Timestamp error (:issue:`53`)
Version 0.3.4
^^^^^^^^^^^^^
**Release Date**: 2017-11-2
+4 -3
View File
@@ -442,7 +442,7 @@ class TestExchangeBundle:
data_frequency = 'minute'
exchange = get_exchange(exchange_name)
asset = exchange.get_asset('eth_btc')
asset = exchange.get_asset('neo_usd')
self._bundle_to_csv(
asset=asset,
@@ -456,8 +456,8 @@ class TestExchangeBundle:
def bundle_to_csv(self):
exchange_name = 'bitfinex'
data_frequency = 'minute'
period = '2017-06'
symbol = 'etc_btc'
period = '2017-10'
symbol = 'neo_btc'
exchange = get_exchange(exchange_name)
asset = exchange.get_asset(symbol)
@@ -475,6 +475,7 @@ class TestExchangeBundle:
path=path,
filename=period
)
pass
def _bundle_to_csv(self, asset, exchange, data_frequency, filename,
path=None):