mirror of
https://github.com/wassname/catalyst.git
synced 2026-07-07 04:28:41 +08:00
ENH: Add IPython cell magic.
When zipline is imported it checks whether it runs in the IPython notebook. If it does, it registers a %%zipline magic that takes the same arguments as the CLI with the addition of a -o for specifying the output variable to store the performance frame in. The algo code in the cell is, as of yet, executed in its own environment rather than that of the IPython NB which is probably what we want. Also adds cli option to save the perf dataframe to a pickle file. Also adds an IPython notebook buyapple example.
This commit is contained in:
@@ -31,6 +31,12 @@ from . algorithm import TradingAlgorithm
|
||||
|
||||
from . import api
|
||||
|
||||
try:
|
||||
ip = get_ipython() # flake8: noqa
|
||||
ip.register_magic_function(utils.parse_cell_magic, "line_cell", "zipline")
|
||||
except:
|
||||
pass
|
||||
|
||||
__all__ = [
|
||||
'data',
|
||||
'finance',
|
||||
|
||||
@@ -126,6 +126,7 @@ class TradingAlgorithm(object):
|
||||
self.sources = []
|
||||
|
||||
self._recorded_vars = {}
|
||||
self.namespace = kwargs.get('namespace', {})
|
||||
|
||||
self.logger = None
|
||||
|
||||
@@ -177,16 +178,15 @@ class TradingAlgorithm(object):
|
||||
self._analyze = None
|
||||
|
||||
if self.algoscript is not None:
|
||||
self.ns = {}
|
||||
exec_(self.algoscript, self.ns)
|
||||
self._initialize = self.ns.get('initialize', None)
|
||||
if 'handle_data' not in self.ns:
|
||||
exec_(self.algoscript, self.namespace)
|
||||
self._initialize = self.namespace.get('initialize', None)
|
||||
if 'handle_data' not in self.namespace:
|
||||
raise ValueError('You must define a handle_data function.')
|
||||
else:
|
||||
self._handle_data = self.ns['handle_data']
|
||||
self._handle_data = self.namespace['handle_data']
|
||||
|
||||
# Optional analyze function, gets called after run
|
||||
self._analyze = self.ns.get('analyze', None)
|
||||
self._analyze = self.namespace.get('analyze', None)
|
||||
|
||||
elif kwargs.get('initialize', False) and kwargs.get('handle_data'):
|
||||
if self.algoscript is not None:
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -16,9 +16,11 @@
|
||||
|
||||
from zipline.api import order, record
|
||||
|
||||
|
||||
def initialize(context):
|
||||
pass
|
||||
|
||||
|
||||
def handle_data(context, data):
|
||||
order('AAPL', 10)
|
||||
record(AAPL=data['AAPL'].price)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
|
||||
def analyze(context, perf):
|
||||
ax1 = plt.subplot(211)
|
||||
perf.portfolio_value.plot(ax=ax1)
|
||||
|
||||
@@ -26,6 +26,7 @@ from zipline.api import order_target, record, symbol
|
||||
from collections import deque as moving_window
|
||||
import numpy as np
|
||||
|
||||
|
||||
def initialize(context):
|
||||
# Add 2 windows, one with a long window, one
|
||||
# with a short window.
|
||||
@@ -33,6 +34,7 @@ def initialize(context):
|
||||
context.short_window = moving_window(maxlen=100)
|
||||
context.long_window = moving_window(maxlen=300)
|
||||
|
||||
|
||||
def handle_data(context, data):
|
||||
# Save price to window
|
||||
context.short_window.append(data[symbol('AAPL')].price)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
|
||||
def analyze(context, perf):
|
||||
fig = plt.figure()
|
||||
ax1 = fig.add_subplot(211)
|
||||
@@ -11,7 +12,8 @@ def analyze(context, perf):
|
||||
|
||||
perf_trans = perf.ix[[t != [] for t in perf.transactions]]
|
||||
buys = perf_trans.ix[[t[0]['amount'] > 0 for t in perf_trans.transactions]]
|
||||
sells = perf_trans.ix[[t[0]['amount'] < 0 for t in perf_trans.transactions]]
|
||||
sells = perf_trans.ix[
|
||||
[t[0]['amount'] < 0 for t in perf_trans.transactions]]
|
||||
ax2.plot(buys.index, perf.short_mavg.ix[buys.index],
|
||||
'^', markersize=10, color='m')
|
||||
ax2.plot(sells.index, perf.short_mavg.ix[sells.index],
|
||||
|
||||
@@ -13,6 +13,6 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from .cli import run_algo, parse_args
|
||||
from .cli import run_algo, parse_args, parse_cell_magic
|
||||
|
||||
__all__ = ['run_algo', 'parse_args']
|
||||
__all__ = ['run_algo', 'parse_args', 'parse_cell_magic']
|
||||
|
||||
+53
-18
@@ -16,17 +16,16 @@
|
||||
import sys
|
||||
import os
|
||||
import argparse
|
||||
import ConfigParser
|
||||
from copy import copy
|
||||
|
||||
import datetime
|
||||
from six import print_
|
||||
from six.moves import configparser
|
||||
import pandas as pd
|
||||
|
||||
try:
|
||||
from pygments import highlight
|
||||
from pygments.lexers import PythonLexer
|
||||
from pygments.formatters import TerminalFormatter
|
||||
from pygments.styles import STYLE_MAP
|
||||
PYGMENTS = True
|
||||
except:
|
||||
PYGMENTS = False
|
||||
@@ -42,7 +41,8 @@ DEFAULTS = {
|
||||
'symbols': 'AAPL'
|
||||
}
|
||||
|
||||
def parse_args(argv):
|
||||
|
||||
def parse_args(argv, ipython_mode=False):
|
||||
# Parse any conf_file specification
|
||||
# We make this parser with add_help=False so that
|
||||
# it doesn't parse -h and print help.
|
||||
@@ -51,7 +51,7 @@ def parse_args(argv):
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
# Turn off help, so we print all options in response to -h
|
||||
add_help=False
|
||||
)
|
||||
)
|
||||
conf_parser.add_argument("-c", "--conf_file",
|
||||
help="Specify config file",
|
||||
metavar="FILE")
|
||||
@@ -60,7 +60,7 @@ def parse_args(argv):
|
||||
defaults = copy(DEFAULTS)
|
||||
|
||||
if args.conf_file:
|
||||
config = ConfigParser.SafeConfigParser()
|
||||
config = configparser.SafeConfigParser()
|
||||
config.read([args.conf_file])
|
||||
defaults.update(dict(config.items("Defaults")))
|
||||
|
||||
@@ -82,10 +82,34 @@ def parse_args(argv):
|
||||
parser.add_argument('--capital_base')
|
||||
parser.add_argument('--source', choices=('yahoo',))
|
||||
parser.add_argument('--symbols')
|
||||
parser.add_argument('--output', '-o')
|
||||
if ipython_mode:
|
||||
parser.add_argument('--local_namespace', action='store_true')
|
||||
|
||||
args = parser.parse_args(remaining_argv)
|
||||
|
||||
return(vars(args))
|
||||
|
||||
|
||||
def parse_cell_magic(line, cell):
|
||||
"""Parse IPython magic"""
|
||||
args_list = line.split(' ')
|
||||
args = parse_args(args_list, ipython_mode=True)
|
||||
|
||||
local_namespace = args.pop('local_namespace', False)
|
||||
# By default, execute inside IPython namespace
|
||||
if not local_namespace:
|
||||
args['namespace'] = get_ipython().user_ns # flake8: noqa
|
||||
|
||||
perf = run_algo(print_algo=False, algo_text=cell, **args)
|
||||
|
||||
# If we are running inside NB, do not output to file but create a
|
||||
# variable instead
|
||||
output_var_name = args.pop('output', None)
|
||||
if output_var_name is not None:
|
||||
get_ipython().user_ns[output_var_name] = perf # flake8: noqa
|
||||
|
||||
|
||||
def run_algo(print_algo=True, **kwargs):
|
||||
start = pd.Timestamp(kwargs['start'], tz='UTC')
|
||||
end = pd.Timestamp(kwargs['end'], tz='UTC')
|
||||
@@ -93,29 +117,40 @@ def run_algo(print_algo=True, **kwargs):
|
||||
symbols = kwargs['symbols'].split(',')
|
||||
|
||||
if kwargs['source'] == 'yahoo':
|
||||
source = zipline.data.load_bars_from_yahoo(stocks=symbols, start=start, end=end)
|
||||
source = zipline.data.load_bars_from_yahoo(
|
||||
stocks=symbols, start=start, end=end)
|
||||
else:
|
||||
raise NotImplementedError('Source %s not implemented.' % kwargs['source'])
|
||||
raise NotImplementedError(
|
||||
'Source %s not implemented.' % kwargs['source'])
|
||||
|
||||
algo_fname = kwargs['algofile']
|
||||
with open(algo_fname, 'r') as fd:
|
||||
algo_text = fd.read()
|
||||
algo_text = kwargs.get('algo_text', None)
|
||||
if algo_text is None:
|
||||
# Expect algofile to be set
|
||||
algo_fname = kwargs['algofile']
|
||||
with open(algo_fname, 'r') as fd:
|
||||
algo_text = fd.read()
|
||||
|
||||
analyze_fname = os.path.splitext(algo_fname)[0] + '_analyze.py'
|
||||
if os.path.exists(analyze_fname):
|
||||
with open(analyze_fname, 'r') as fd:
|
||||
# Simply append
|
||||
algo_text += fd.read()
|
||||
analyze_fname = os.path.splitext(algo_fname)[0] + '_analyze.py'
|
||||
if os.path.exists(analyze_fname):
|
||||
with open(analyze_fname, 'r') as fd:
|
||||
# Simply append
|
||||
algo_text += fd.read()
|
||||
|
||||
if print_algo:
|
||||
if PYGMENTS:
|
||||
highlight(algo_text, PythonLexer(), TerminalFormatter(), outfile=sys.stdout)
|
||||
highlight(algo_text, PythonLexer(), TerminalFormatter(),
|
||||
outfile=sys.stdout)
|
||||
else:
|
||||
print algo_text
|
||||
print_(algo_text)
|
||||
|
||||
algo = zipline.TradingAlgorithm(script=algo_text,
|
||||
namespace=kwargs.get('namespace', {}),
|
||||
capital_base=float(kwargs['capital_base']))
|
||||
|
||||
perf = algo.run(source)
|
||||
|
||||
output_fname = kwargs.get('output', None)
|
||||
if output_fname is not None:
|
||||
perf.to_pickle(output_fname)
|
||||
|
||||
return perf
|
||||
|
||||
Reference in New Issue
Block a user