The 4 Honey Badger Modes:
http://i.imgur.com/aK99fwK.png
[2015-02-16 23:00:00] Start Date: 2011-12-18 04:00:00
[2015-02-16 23:00:00] Day: 1157 Trades: 91 Frequency 12.7
[2015-02-16 23:00:00] USD 3185.0 / 18745956.9 / 588470.1 ROI
[2015-02-16 23:00:00] BTC 1000.0 / 80366.3 / 7936.6 ROI
[2015-02-16 23:00:00] ***************************************
[2015-02-16 23:00:00] Buy and Hold Gain.: 73.2X
[2015-02-16 23:00:00] Asset Gain........: 80.4X
[2015-02-16 23:00:00] Currency Gain.....: 5885.7X
I trade at tradewave.net and I developed the "Honey Badger" which is a very popular, open source, SMA framework for trading cryptocurrency pairs BTCUSD and LTCUSD. Tradewave is relatively new and very limited on backtesting data. I would like to expose my algo to broader data sets for refinement here at Quantopian. I also have several other scripts I'd like to share... but I need some help getting started; namely: If I could get you guys to port/help me port my basic "Honey Badger" from Tradewave-Python to Quantopian-Python, I suspect I'd catch on rather quickly thereafter and be able to share more in your native "python"; without having to stumble through the syntax differences of ordering, calling talib, selecting trading pairs, logging, plotting, etc.
Here's a backtest 2011 to present:
http://pastebin.com/rjN9SnP5
Here's a screen capture:
http://i.imgur.com/rDc8Hz4.png
With a bit of refinement beyond the open source presented here you can get it to trade like this:
http://i.imgur.com/3bQ5G5N.png ...for 2000X asset gain :D
Here's the open source version script, it trades aggregated 12h SMA's. Average trade frequency is once every 2 weeks. Any help is appreciated, let me know if you have any questions. I look forward to learning more about the Quantopian platform!
I appreciate any input... with or without help; goal = open source Honey Badger port to Quantopian and trading the 2000 YHOO bubble by this time next week, because I NEED more backtest data! :D
...and because Quantopian needs the Honey Badger algo ;)
ETA SEE NEXT POST; 95% PORTED ...but I still need some help accessing SMA data.
Here's the script in Tradewave Python:
import talib
import time
# Run a 3 month backest up to most recent candle in the interval you
# intend to run LIVE, enter 'KEYS' displayed at end of log below:
KEY1 = 0
KEY2 = 0
KEY3 = 0
def initialize():
#These are my stored objects
storage.ratio = n = (43200 / info.interval)
storage.overbought = storage.get('overbought', 0)
storage.prev_mode = storage.get('prev_mode', 0)
storage.trades = storage.get('trades', 0)
storage.action = storage.get('action', 0)
storage.signal = storage.get('signal', 0)
storage.hold = storage.get('hold', 0)
storage.mode = storage.get('mode', 0)
storage.currency = storage.get('currency', 0)
storage.assets = storage.get('assets', 0)
storage.start_currency = storage.get('start_currency', 0)
storage.start_assets = storage.get('start_assets', 0)
def instrument():
# This detects the currency pair chosen for backtesting;
# bitcoin, litecoin, Euro, and USD are the options
# It then accesses my current portfolio balance on each tick
# and extracts "USD" "BTC" "LTC" or "EUR" from "info.primary_pair"
pair = info.primary_pair
if pair == pairs.btc_usd:
pair = 'btcusd'
if pair == pairs.ltc_usd:
pair = 'ltcusd'
if pair == pairs.ltc_btc:
pair = 'ltcbtc'
if pair == pairs.btc_eur:
pair = 'btceur'
if pair == pairs.ltc_eur:
pair = 'ltceur'
currency_code = ''.join(list((pair)[3:6]))
asset_code = ''.join(list((pair)[0:3]))
instrument_pair = asset_code + '_' + currency_code
storage.instrument = pairs[instrument_pair]
storage.currency = portfolio[currencies[currency_code]]
storage.assets = portfolio[currencies[asset_code]]
storage.currency_CODE = (currency_code).upper()
storage.asset_CODE = (asset_code).upper()
def ma12h(timeperiod, depth):
# This definition calculates SMA via TAlib
# for 43200 (12h) candles, regardless of candle size the bot is deployed on
# Depth is the number of candles into the past
sma = data(interval=43200)[info.primary_pair][depth].ma(timeperiod)
return sma
def chart():
# This just plots all the indicators, including
# "mode" which is on a secondary Y axis
mode = storage.mode
if storage.mode < 2:
mode = 1
plot('ma2', storage.ma2)
plot('ma30', storage.ma30)
plot('floor', storage.floor)
plot('moon', storage.moon)
plot('ma60', storage.ma60)
plot('ma90', storage.ma90)
plot('ma150', storage.ma150)
plot('resistance', storage.resistance)
plot('mode', mode, secondary=True)
# 1 = green dragon
# 2 = capitulation
# 3 = red dragon
# 4 = cat bounce
buy = 0
sell = 0
if storage.signal == 1:
buy = 0.5
if storage.signal == -1:
sell = -0.5
plot('buy_signal', buy, secondary=True)
plot('sell_signal', sell, secondary=True)
if info.tick == 0:
plot('offset', -15, secondary=True)
def indicators():
# This definition moves each SMA or expression thereof to a stored object
storage.ma2 = (ma12h(2, 0))
storage.ma30 = (ma12h(30, 0))
storage.ma55 = (ma12h(55, 0))
storage.ma60 = (ma12h(60, 0))
storage.ma90 = (ma12h(90, 0))
storage.ma150 = (ma12h(150, 0))
storage.ma2i = (ma12h(2, -1))
storage.ma30i = (ma12h(30, -1))
storage.ma55i = (ma12h(55, -1))
storage.ma60i = (ma12h(60, -1))
storage.ma90i = (ma12h(90, -1))
storage.ma150i = (ma12h(150, -1))
storage.floor = Decimal(0.75) * storage.ma55
storage.moon = Decimal(1.05) * storage.ma55
storage.resistance = (storage.ma30 + Decimal(2.8) *
(storage.ma30 - storage.ma60))
# Here I define my starting balance
if info.tick == 0:
storage.start_currency = (Decimal(0.00001) +
storage.currency + storage.assets * storage.ma2)
storage.start_assets = (Decimal(0.00001) +
storage.assets + storage.currency / storage.ma2)
if storage.currency + storage.assets == 0:
log('Zero Starting Portfolio')
raise Stop()
# Here I define whether or not I'm holding assets and currency on each tick
storage.holding_assets = False
storage.holding_currency = False
if storage.currency > (storage.ma2 * Decimal(0.12)):
storage.holding_currency = True
if storage.assets > 0.12:
storage.holding_assets = True
def mode_select():
# Here I define "Green Dragon and Red Dragon"
# Cat Bounce always follows Red Dragon
# Capitulation always follows Green Dragon
if storage.hold <= 0:
ma2 = storage.ma2
ma30 = storage.ma30
ma60 = storage.ma60
ma90 = storage.ma90
ma150 = storage.ma150
ma30i = storage.ma30i
ma60i = storage.ma60i
ma90i = storage.ma90i
ma150i = storage.ma150i
resistance = storage.resistance
# Green Dragon Market
if ((ma30 > ma60) and
(ma60 > ma90) and
(ma90 > ma150) and
(ma2 > ma30) and
(ma30 > Decimal(1.002) * ma30i) and
(ma60 > Decimal(1.002) * ma60i) and
(ma90 > Decimal(1.002) * ma90i)):
storage.mode = 1
if ma2 > resistance:
storage.overbought = 4*43200
if storage.overbought > 0:
storage.overbought -= info.interval
storage.mode = -1
# Red Dragon Market
elif ((resistance < ma150) and
(ma2 < ma90) and
(ma2 < ma150) and
(ma150 < ma150i) and
(resistance < ma90)):
storage.mode = 3
# Not Dragon Market
else:
if storage.prev_mode == (3 or 4):
storage.mode = 4 # Cat Bounce
if abs(storage.prev_mode) == (1 or 2):
storage.mode = 2 # Capitulation
def mode_3():
# This definition is used to trade Red Dragon
ma2 = storage.ma2
ma2i = storage.ma2i
ma30 = storage.ma30
signal = 0
if ma2 < storage.floor:
signal = 1
elif ma2 > storage.moon:
signal = -1
elif ((ma2 < ma2i) and
(ma2 < ma30) and
(ma2i > ma30)):
signal = -1
return signal
def think():
# This is the primary trading logic
action = 0
signal = 0
mode_select()
n = storage.ratio
ma2 = storage.ma2
hold = storage.hold
mode = storage.mode
ma30 = storage.ma30
ma60 = storage.ma60
ma90 = storage.ma90
ma90i = storage.ma90i
ma150 = storage.ma150
prev_mode = storage.prev_mode
holding_assets = storage.holding_assets
holding_currency = storage.holding_currency
if hold <= 0:
# MODE <2 - GREEN DRAGON
if mode == 0:
signal = 1
hold = 1
if holding_currency:
log('CRYPTO LONG')
action = 1
hold = 1
if mode == 1:
signal = 1
hold = 1
if holding_currency:
log('GREEN DRAGON')
action = 1
hold = 1
if mode == -1:
signal = -1
hold = 0
if holding_assets:
log('OVERBOUGHT')
action = -1
hold = 1
# MODE 2 - CAPITULATION
if ((mode == 2) and (prev_mode != 2)):
signal = -1
if holding_assets:
log('CAPITULATION')
action = -1
hold = 1
if mode == prev_mode == 2:
if ma2 < ma90:
signal = 1
# hold = 0
if holding_currency:
log('DESPAIR')
action = 1
hold = 1
if ((ma2 > Decimal(1.1) * ma90) and
(ma2 > ma60)):
signal = -1
# hold = 0
if holding_assets:
log('FINAL RUN OF THE BULLS - B')
action = -1
hold = 2
# MODE 3 - RED DRAGON
if ((mode == 3) and (prev_mode != 3)):
signal = -1
hold = 0
if holding_assets:
log('RED DRAGON')
action = -1
hold = 5
if mode == prev_mode == 3:
signal_3 = mode_3()
if signal_3 == 1:
signal = 1
hold = 5
if holding_currency:
log('PURGATORY')
action = 1
hold = 5
elif signal_3 == -1:
signal = -1
hold = 0
if holding_assets:
log('DEEPER')
action = -1
hold = 1
# MODE 4 - CAT BOUNCE
if ((mode == 4) and (prev_mode != 4)):
signal = 1
hold = 0
if holding_currency:
log('HONEY')
action = 1
hold = 2
if mode == prev_mode == 4:
if ((ma2 < Decimal(1.05) * ma30) and
(ma2 > ma60) and
(ma90 > Decimal(1.003) * ma90i)):
signal = -1
hold = 1
if holding_assets:
log('KARMA')
action = -1
hold = 1
if ((ma2 < ma90) and
(ma90 < ma60) and
(ma90 < ma30) and
(ma90 > ma90i)):
signal = 1
hold = 0
if holding_currency:
log('GOLD')
action = 1
hold = 1
storage.hold = Decimal(hold) * 86400
storage.hold -= info.interval
storage.signal = signal
storage.action = action
storage.prev_mode = storage.mode
def order():
# Here is how I actually place orders at Tradewave
if storage.action == 1:
if storage.holding_currency:
try:
order = buy(info.primary_pair)
storage.trades += 1
email(order.price,
subject='**ALERT** HONEY BADGER SAYS: BUY OR CRY')
except TradewaveFundsError as e:
log('Not enough currency!')
except TradewaveInvalidOrderError as e:
log('Unable to place buy order: %s' % e.message)
if storage.action == -1:
if storage.holding_assets:
try:
order = sell(info.primary_pair)
storage.trades += 1
email(order.price,
subject='**ALERT** HONEY BADGER SAYS: FIAT TIME')
except TradewaveFundsError as e:
log('Not enough assets!')
except TradewaveInvalidOrderError as e:
log('Unable to place buy order: %s' % e.message)
if abs(storage.action) == 1:
report()
def report():
# This is used to periodically report ROI via the log
days = (info.current_time - info.begin) / 86400
trades = storage.get('trades', 0)
if trades == 0:
frequency = 0
else:
frequency = Decimal(days) / Decimal(trades)
start_date = time.strftime(
'%Y-%m-%d %H:%M:%S', time.localtime(info.begin))
potential_assets = storage.assets + storage.currency / storage.ma2
potential_currency = storage.currency + storage.assets * storage.ma2
start_assets = storage.start_assets
start_currency = storage.start_currency
ROI_currency = (100 * potential_currency / start_currency) - 100
ROI_assets = (100 * potential_assets / start_assets) - 100
log('Start Date: %s' % start_date)
log('Day: %s Trades: %s Frequency %.1f' % (days, trades, frequency))
log('%s %.1f / %.1f / %.1f ROI' %
(storage.currency_CODE, start_currency,
potential_currency, ROI_currency))
log('%s %.1f / %.1f / %.1f ROI' %
(storage.asset_CODE, start_assets, potential_assets, ROI_assets))
log('***************************************')
def tick():
# Tick is called on every tick and directs the other definitions in the script
if info.tick == 0:
storage.hold = KEY1
storage.mode = storage.prev_mode = KEY2
storage.overbought = KEY3
instrument()
indicators()
chart()
think()
if info.tick > 0:
order()
if 1: # on/off COUNT DAYS
n = storage.ratio
if info.tick % (2 * n) == 0:
log(info.tick / (2 * n))
if storage.hold < 0:
storage.hold = 0
def stop():
# This is the final report that displays in the log during backtesting on the last tick
bnh_gain = ((storage.start_assets * storage.ma2) /
storage.start_currency)
currency_gain = ((storage.currency + storage.assets * storage.ma2) /
storage.start_currency)
asset_gain = currency_gain / bnh_gain
if storage.assets*storage.ma2 > storage.currency:
holding = storage.asset_CODE
else:
holding = storage.currency_CODE
log('***************************************')
log('***************************************')
log('Honey Badger v1.0 80X by litepresence')
log('')
report()
log('Buy and Hold Gain.: %.1fX' % bnh_gain)
log('Asset Gain........: %.1fX' % asset_gain)
log('Currency Gain.....: %.1fX' % currency_gain)
log('**** INITIALIZATION KEYS ****')
log('KEY1 = %s' % int(storage.hold))
log('KEY2 = %s' % storage.mode)
log('KEY3 = %s' % storage.overbought)
log('HOLDING %s' % holding)
Thanks for reading! I appreciate your help getting acquainted to Quantopian!
Here are some other noteworthy scripts I've written in Tradewave-Python you might find interesting:
Iceberg Limit Orders:
https://discuss.tradewave.net/t/iceberg-limit-orders-v1-0-beta-litepresence
Parabolic SAR Custom without TAlib:
https://discuss.tradewave.net/t/parabolic-sar-custom-without-ta-lib