http://sebastiannilsson.com/en/blogg/algorithmic-trading-with-python/
I have been experimenting with algorithmic trading for a couple of weeks. Zipline is a Python library for backtesting trading algorithms and I would like to share one of the algorithms I made.
- import talib
- from zipline.api import record, order_target, history, add_history
- import dateutil
- import logging
- from zipline.utils.factory import load_from_yahoo
- from zipline.finance.slippage import FixedSlippage
- from zipline.algorithm import TradingAlgorithm
- from zipline.finance import commission
- logging.basicConfig(level=logging.DEBUG)
- # initialize algorithm
- def initialize(context):
- logging.debug('enter initialize')
- context.set_slippage(FixedSlippage())
- context.set_commission(commission.PerTrade(cost=5))
- context.LOW_RSI = initialize.low_RSI
- context.HIGH_RSI = initialize.high_RSI
- context.rsi_window = initialize.rsi_window
- add_history(context.rsi_window, '1d', 'price')
- context.i = 0
- context.invested = False
- # default parameters for algorithm
- initialize.rsi_window = 15
- initialize.low_RSI = 30
- initialize.high_RSI = 70
- # Will be called on every trade event for the securities you specify.
- def handle_data(context, data):
- logging.debug('enter handle_data')
- context.i += 1
- if context.i < context.rsi_window:
- return
- # get the last RSI value
- prices = history(context.rsi_window, '1d', 'price')
- sec_rsi = talib.RSI(
- prices[context.security].values,
- timeperiod=context.rsi_window - 1)
- # buy and sell flags
- buy = False
- sell = False
- if sec_rsi[-1] < context.LOW_RSI and not context.invested:
- # RSI under 30 indicates oversold, time to buy
- order_target(context.security, 1000)
- logging.debug('Buying {}'.format(context.security))
- context.invested = True
- buy = True
- elif sec_rsi[-1] > context.HIGH_RSI and context.invested:
- # RSI over 70 indicates overbought, sell everything
- order_target(context.security, 0)
- logging.debug('Selling {}'.format(context.security))
- context.invested = False
- sell = True
- # record data for each time increment
- record(secRSI=sec_rsi[-1],
- price=data[context.security].price,
- buy=buy,
- sell=sell)
- logging.info(context.portfolio.cash)
- def run_algorithm(
- security='AAPL',
- start_date='20100101',
- end_date='20150101',
- initial_cash=100000,
- rsi_window=15,
- low_RSI=30,
- high_RSI=70):
- logging.debug('run_algorithm begin')
- # dates
- start = dateutil.parser.parse(start_date)
- end = dateutil.parser.parse(end_date)
- # get data from yahoo
- data = load_from_yahoo(stocks=[security], indexes={}, start=start, end=end)
- logging.debug('done loading from yahoo. {} {} {}'.format(
- security, start_date, end_date))
- # create and run algorithm
- algo = TradingAlgorithm(
- initialize=initialize,
- handle_data=handle_data,
- capital_base=initial_cash)
- algo.security = security
- initialize.low_RSI = low_RSI
- initialize.high_RSI = high_RSI
- initialize.rsi_window = rsi_window
- logging.debug('starting to run algo...')
- results = algo.run(data).dropna()
- logging.debug('done running algo')
- return results
- if __name__ == '__main__':
- import matplotlib.pyplot as plt
- # run algorithm and get results
- results = run_algorithm(
- security='AAPL',
- start_date='20100101',
- end_date='20150101',
- initial_cash=100000,
- rsi_window=15,
- low_RSI=30,
- high_RSI=70)
- # get s&p500 and nasdaq indexes
- index_data = load_from_yahoo(
- stocks=['^gspc', '^ixic'],
- indexes={},
- start=results.index[0],
- end=results.index[-1])
- # portfolio value, stock holdings and S&P 500 index
- fig = plt.figure(figsize=(12, 6))
- ax11 = fig.add_subplot(311)
- ax12, ax13 = ax11.twinx(), ax11.twinx()
- ax13.spines['right'].set_position(('axes', 1.07))
- ax11.set_ylabel('portfolio value', color='blue')
- ax12.set_ylabel('holdings', color='green')
- ax13.set_ylabel('S&P 500', color='red')
- # portfolio value
- ax11.plot(results.index, results.portfolio_value, color='blue')
- # holdings (number of stocks owned)
- holdings = [0 if t == [] else t[0]['amount'] for t in results.positions]
- ax12.plot(results.index, holdings, color='green')
- ax12.set_ylim([min(holdings) - 30, max(holdings) + 30])
- # index
- ax13.plot(index_data.index, index_data['^gspc'], color='red')
- # algo visualization
- ax21 = fig.add_subplot(312)
- ax21.set_ylabel('stock price', color='blue')
- ax22 = ax21.twinx()
- ax22.set_ylabel('rsi', color='red')
- # stock
- ax21.plot(results.index, results.price, color='blue')
- # add sell and buy flags on top of stock price
- ax21.plot(
- results.ix[results.buy].index,
- results.price[results.buy],
- '^',
- markersize=10,
- color='green')
- ax21.plot(
- results.ix[results.sell].index,
- results.price[results.sell],
- 'v',
- markersize=10,
- color='red')
- # rsi value
- ax22.plot(results.index, results.secRSI, color='red')
- # add lines to show under- and over value indicator
- ax22.plot([results.index[0], results.index[-1]], [30, 30], 'k-')
- ax22.plot([results.index[0], results.index[-1]], [70, 70], 'k-')
- # portfolio value, stock value and index in percentage
- ax31 = fig.add_subplot(313)
- ax32, ax33 = ax31.twinx(), ax31.twinx() # share x for other plots
- ax31.set_ylabel('algo %', color='blue')
- ax32.set_ylabel('snp index %', color='green')
- ax33.set_ylabel('stock %', color='red')
- ax33.spines['right'].set_position(('axes', 1.07))
- # portfolio value
- ax31.plot(
- results.index,
- results.portfolio_value / results.portfolio_value[0] * 100 - 100,
- color='blue')
- # index
- ax32.plot(
- index_data.index,
- index_data['^gspc'] / index_data['^gspc'][0] * 100 - 100,
- color='green')
- # stock value
- ax33.plot(
- results.index,
- results.price /
- results.price[0] * 100 - 100,
- color='red')
- plt.show()
If you get it working you should see a plot similar to this one:
If you are observant, it is easy to see that the performance of this algorithm is not good enough to be used on a real portfolio, and it is more of a test.
Links:
'Data Mining & R' 카테고리의 다른 글
TensorFlow - google deep learning open source (0) | 2016.06.23 |
---|---|
web 에서 주식data 가져오기 (0) | 2016.05.11 |
quantiacs : algorithmic trading competition (0) | 2016.05.10 |
Trading VXX with nearest neighbors prediction (0) | 2016.05.10 |
Backtesting with TWP backtesting module (0) | 2016.05.10 |