mirror of
https://github.com/wassname/catalyst.git
synced 2026-07-27 11:20:45 +08:00
@@ -224,11 +224,11 @@ class FinanceTestCase(TestCase):
|
||||
"Portfolio should have one position."
|
||||
)
|
||||
|
||||
SID = self.zipline_test_config['sid']
|
||||
sid = self.zipline_test_config['sid']
|
||||
self.assertEqual(
|
||||
zipline.get_positions()[SID]['sid'],
|
||||
SID,
|
||||
"Portfolio should have one position in " + str(SID)
|
||||
zipline.get_positions()[sid]['sid'],
|
||||
sid,
|
||||
"Portfolio should have one position in " + str(sid)
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
from datetime import timedelta
|
||||
from collections import defaultdict
|
||||
from unittest2 import TestCase
|
||||
|
||||
import zipline.utils.factory as factory
|
||||
from zipline.finance.vwap import DailyVWAP, VWAPTransform
|
||||
from zipline.finance.returns import ReturnsFromPriorClose
|
||||
from zipline.finance.movingaverage import MovingAverage
|
||||
from zipline.lines import SimulatedTrading
|
||||
from zipline.core.devsimulator import AddressAllocator
|
||||
|
||||
allocator = AddressAllocator(1000)
|
||||
|
||||
class ZiplineWithTransformsTestCase(TestCase):
|
||||
leased_sockets = defaultdict(list)
|
||||
|
||||
def setUp(self):
|
||||
# skip ahead 100 spots
|
||||
allocator.lease(100)
|
||||
self.trading_environment = factory.create_trading_environment()
|
||||
self.zipline_test_config = {
|
||||
'allocator':allocator,
|
||||
'sid':133
|
||||
}
|
||||
|
||||
def test_vwap_tnfm(self):
|
||||
zipline = SimulatedTrading.create_test_zipline(
|
||||
**self.zipline_test_config
|
||||
)
|
||||
vwap = VWAPTransform("vwap_10", daycount=10)
|
||||
zipline.add_transform(vwap)
|
||||
|
||||
zipline.simulate(blocking=True)
|
||||
|
||||
self.assertTrue(zipline.sim.ready())
|
||||
self.assertFalse(zipline.sim.exception)
|
||||
|
||||
class FinanceTransformsTestCase(TestCase):
|
||||
def setUp(self):
|
||||
self.trading_environment = factory.create_trading_environment()
|
||||
|
||||
def test_vwap(self):
|
||||
|
||||
trade_history = factory.create_trade_history(
|
||||
133,
|
||||
[10.0, 10.0, 10.0, 11.0],
|
||||
[100, 100, 100, 300],
|
||||
timedelta(days=1),
|
||||
self.trading_environment
|
||||
)
|
||||
|
||||
vwap = DailyVWAP(days=2)
|
||||
for trade in trade_history:
|
||||
vwap.update(trade)
|
||||
|
||||
self.assertEqual(vwap.vwap, 10.75)
|
||||
|
||||
|
||||
def test_returns(self):
|
||||
trade_history = factory.create_trade_history(
|
||||
133,
|
||||
[10.0, 10.0, 10.0, 11.0],
|
||||
[100, 100, 100, 300],
|
||||
timedelta(days=1),
|
||||
self.trading_environment
|
||||
)
|
||||
|
||||
returns = ReturnsFromPriorClose()
|
||||
for trade in trade_history:
|
||||
returns.update(trade)
|
||||
|
||||
|
||||
self.assertEqual(returns.returns, .1)
|
||||
|
||||
|
||||
def test_moving_average(self):
|
||||
trade_history = factory.create_trade_history(
|
||||
133,
|
||||
[10.0, 10.0, 10.0, 11.0],
|
||||
[100, 100, 100, 300],
|
||||
timedelta(days=1),
|
||||
self.trading_environment
|
||||
)
|
||||
|
||||
ma = MovingAverage(days=2)
|
||||
for trade in trade_history:
|
||||
ma.update(trade)
|
||||
|
||||
|
||||
self.assertEqual(ma.average, 10.5)
|
||||
@@ -17,7 +17,7 @@ class DataSource(Component):
|
||||
converting to a dict, and calling send(map).
|
||||
|
||||
Every datasource has a dict property to hold filters::
|
||||
- key -- name of the filter, e.g. SID
|
||||
- key -- name of the filter, e.g. sid
|
||||
- value -- a primitive representing the filter. e.g. a list of ints.
|
||||
|
||||
Modify the datasource's filters via the set_filter(name, value)
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
from feed import Feed
|
||||
|
||||
import zipline.protocol as zp
|
||||
from zipline.protocol import COMPONENT_TYPE
|
||||
from zipline.components.aggregator import Aggregate
|
||||
|
||||
from collections import Counter
|
||||
|
||||
@@ -160,6 +160,9 @@ class TradeSimulationClient(Component):
|
||||
|
||||
def get_data(self):
|
||||
for event in self.event_queue:
|
||||
#alias the dt as datetime
|
||||
event.datetime = event.dt
|
||||
self.event_data[event['sid']] = event
|
||||
|
||||
self.event_queue = []
|
||||
return self.event_data
|
||||
|
||||
@@ -5,10 +5,17 @@ from zipline.transforms.base import BaseTransform
|
||||
|
||||
class MovingAverageTransform(BaseTransform):
|
||||
|
||||
def init(self, name, daycount=3):
|
||||
self.daycount = daycount
|
||||
|
||||
def init(self, name, days=3):
|
||||
self.state = {}
|
||||
self.state['name'] = name
|
||||
self.days = days
|
||||
self.by_sid = defaultdict(self._create)
|
||||
|
||||
@property
|
||||
def get_id(self):
|
||||
return self.state['name']
|
||||
|
||||
def transform(self, event):
|
||||
cur = self.by_sid[event.sid]
|
||||
cur.update(event)
|
||||
@@ -16,12 +23,12 @@ class MovingAverageTransform(BaseTransform):
|
||||
return self.state
|
||||
|
||||
def _create(self):
|
||||
return MovingAverage(self.daycount)
|
||||
return MovingAverage(self.days)
|
||||
|
||||
class MovingAverage(object):
|
||||
|
||||
def init(self, daycount):
|
||||
self.window = EventWindow(daycount)
|
||||
def __init__(self, days):
|
||||
self.window = EventWindow(days)
|
||||
self.total = 0.0
|
||||
self.average = 0.0
|
||||
|
||||
@@ -43,10 +50,10 @@ class EventWindow(object):
|
||||
Tracks a window of the event history. Use an instance to track the events
|
||||
inside your window to efficiently calculate rolling statistics.
|
||||
"""
|
||||
def init(self, daycount):
|
||||
def __init__(self, days):
|
||||
self.ticks = []
|
||||
self.dropped_ticks = []
|
||||
self.delta = timedelta(days=daycount)
|
||||
self.delta = timedelta(days=days)
|
||||
|
||||
def update(self, event):
|
||||
# add new event
|
||||
|
||||
@@ -4,8 +4,15 @@ from zipline.transforms.base import BaseTransform
|
||||
class ReturnsTransform(BaseTransform):
|
||||
|
||||
def init(self, name):
|
||||
self.state = {}
|
||||
self.state['name'] = name
|
||||
self.by_sid = defaultdict(self._create)
|
||||
|
||||
@property
|
||||
def get_id(self):
|
||||
return self.state['name']
|
||||
|
||||
|
||||
def transform(self, event):
|
||||
cur = self.by_sid[event.sid]
|
||||
cur.update(event)
|
||||
@@ -27,7 +34,6 @@ class ReturnsFromPriorClose(object):
|
||||
self.returns = 0.0
|
||||
|
||||
def update(self, event):
|
||||
next_close = None
|
||||
if self.last_close:
|
||||
change = event.price - self.last_close.price
|
||||
self.returns = change / self.last_close.price
|
||||
|
||||
@@ -31,7 +31,7 @@ class TradeDataSource(DataSource):
|
||||
|
||||
def send(self, event):
|
||||
"""
|
||||
Sends the event iff it matches the internal SID filter.
|
||||
Sends the event iff it matches the internal sid filter.
|
||||
:param dict event: is a trade event with data as per
|
||||
:py:func: `zipline.protocol.TRADE_FRAME`
|
||||
:rtype: None
|
||||
@@ -39,7 +39,7 @@ class TradeDataSource(DataSource):
|
||||
|
||||
event.source_id = self.source_id
|
||||
|
||||
if event.sid in self.filter['SID']:
|
||||
if event.sid in self.filter['sid']:
|
||||
message = zp.DATASOURCE_FRAME(event)
|
||||
else:
|
||||
blank = ndict({
|
||||
|
||||
@@ -7,9 +7,15 @@ from zipline.finance.movingaverage import EventWindow
|
||||
class VWAPTransform(BaseTransform):
|
||||
|
||||
def init(self, name, daycount=3):
|
||||
self.state = {}
|
||||
self.state['name'] = name
|
||||
self.daycount = daycount
|
||||
self.by_sid = defaultdict(self.create_vwap)
|
||||
|
||||
@property
|
||||
def get_id(self):
|
||||
return self.state['name']
|
||||
|
||||
def transform(self, event):
|
||||
cur = self.by_sid[event.sid]
|
||||
cur.update(event)
|
||||
@@ -24,12 +30,12 @@ class DailyVWAP(object):
|
||||
A class that tracks the volume weighted average price based on tick
|
||||
updates.
|
||||
"""
|
||||
def init(self, name, daycount=3):
|
||||
self.window = EventWindow(daycount)
|
||||
def __init__(self, days=3):
|
||||
self.window = EventWindow(days)
|
||||
self.flux = 0.0
|
||||
self.volume = 0
|
||||
self.vwap = 0.0
|
||||
self.delta = timedelta(days=daycount)
|
||||
self.delta = timedelta(days=days)
|
||||
|
||||
def update(self, event):
|
||||
|
||||
|
||||
+1
-1
@@ -283,7 +283,7 @@ class SimulatedTrading(object):
|
||||
"""
|
||||
assert isinstance(source, DataSource)
|
||||
self.check_started()
|
||||
source.set_filter('SID', self.algorithm.get_sid_filter())
|
||||
source.set_filter('sid', self.algorithm.get_sid_filter())
|
||||
self.sim.register_components([source])
|
||||
|
||||
# ``id`` is name of source_id, ``get_id`` is the class name
|
||||
|
||||
+40
-41
@@ -2,25 +2,25 @@
|
||||
Algorithm Protocol
|
||||
===================
|
||||
|
||||
For a class to be passed as a trading algorithm to the
|
||||
For a class to be passed as a trading algorithm to the
|
||||
:py:class:`zipline.lines.SimulatedTrading` zipline
|
||||
it must follow an implementation protocol. Examples of this algorithm protocol
|
||||
are provided below.
|
||||
|
||||
The algorithm must expose methods:
|
||||
|
||||
- initialize: method that takes no args, no returns. Simply called to
|
||||
- initialize: method that takes no args, no returns. Simply called to
|
||||
enable the algorithm to set any internal state needed.
|
||||
|
||||
- get_sid_filter: method that takes no args, and returns a list
|
||||
of valid sids. List must have a length between 1 and 10. If None is returned
|
||||
the filter will block all events.
|
||||
|
||||
- handle_data: method that accepts a :py:class:`zipline.protocol_utils.ndict`
|
||||
|
||||
- handle_data: method that accepts a :py:class:`zipline.protocol_utils.ndict`
|
||||
of the current state of the simulation universe. An example data ndict::
|
||||
|
||||
|
||||
+-----------------+--------------+----------------+--------------------+
|
||||
| | SID(133) | SID(134) | SID(135) |
|
||||
| | sid(133) | sid(134) | sid(135) |
|
||||
+=================+==============+================+====================+
|
||||
| price | $10.10 | $22.50 | $13.37 |
|
||||
+-----------------+--------------+----------------+--------------------+
|
||||
@@ -30,23 +30,22 @@ The algorithm must expose methods:
|
||||
+-----------------+--------------+----------------+--------------------+
|
||||
| dt | 6/30/2012 | 6/30/2011 | 6/29/2012 |
|
||||
+-----------------+--------------+----------------+--------------------+
|
||||
|
||||
- set_order: method that accepts a callable. Will be set as the value of the
|
||||
order method of trading_client. An algorithm can then place orders with a
|
||||
valid SID and a number of shares::
|
||||
|
||||
self.order(SID(133), share_count)
|
||||
|
||||
- set_performance: property which can be set equal to the
|
||||
cumulative_trading_performance property of the trading_client. An
|
||||
|
||||
- set_order: method that accepts a callable. Will be set as the value of the
|
||||
order method of trading_client. An algorithm can then place orders with a
|
||||
valid sid and a number of shares::
|
||||
|
||||
self.order(sid(133), share_count)
|
||||
|
||||
- set_performance: property which can be set equal to the
|
||||
cumulative_trading_performance property of the trading_client. An
|
||||
algorithm can then check position information with the
|
||||
Portfolio object::
|
||||
|
||||
self.Portfolio[SID(133)]['cost_basis']
|
||||
|
||||
self.Portfolio[sid(133)]['cost_basis']
|
||||
|
||||
"""
|
||||
|
||||
import zipline.protocol as zp
|
||||
|
||||
class TestAlgorithm():
|
||||
"""
|
||||
@@ -54,7 +53,7 @@ class TestAlgorithm():
|
||||
to verify the orders sent/received, transactions created, and positions
|
||||
at the close of a simulation.
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self, sid, amount, order_count):
|
||||
self.count = order_count
|
||||
self.sid = sid
|
||||
@@ -64,26 +63,26 @@ class TestAlgorithm():
|
||||
self.order = None
|
||||
self.frame_count = 0
|
||||
self.portfolio = None
|
||||
|
||||
|
||||
def initialize(self):
|
||||
pass
|
||||
|
||||
|
||||
def set_order(self, order_callable):
|
||||
self.order = order_callable
|
||||
|
||||
|
||||
def set_portfolio(self, portfolio):
|
||||
self.portfolio = portfolio
|
||||
|
||||
|
||||
def handle_data(self, data):
|
||||
self.frame_count += 1
|
||||
#place an order for 100 shares of sid
|
||||
if self.incr < self.count:
|
||||
self.order(self.sid, self.amount)
|
||||
self.incr += 1
|
||||
|
||||
|
||||
def get_sid_filter(self):
|
||||
return [self.sid]
|
||||
|
||||
return [self.sid]
|
||||
|
||||
#
|
||||
class HeavyBuyAlgorithm():
|
||||
"""
|
||||
@@ -91,7 +90,7 @@ class HeavyBuyAlgorithm():
|
||||
to verify the orders sent/received, transactions created, and positions
|
||||
at the close of a simulation.
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self, sid, amount):
|
||||
self.sid = sid
|
||||
self.amount = amount
|
||||
@@ -100,41 +99,41 @@ class HeavyBuyAlgorithm():
|
||||
self.order = None
|
||||
self.frame_count = 0
|
||||
self.portfolio = None
|
||||
|
||||
|
||||
def initialize(self):
|
||||
pass
|
||||
|
||||
pass
|
||||
|
||||
def set_order(self, order_callable):
|
||||
self.order = order_callable
|
||||
|
||||
|
||||
def set_portfolio(self, portfolio):
|
||||
self.portfolio = portfolio
|
||||
|
||||
|
||||
def handle_data(self, data):
|
||||
self.frame_count += 1
|
||||
#place an order for 100 shares of sid
|
||||
self.order(self.sid, self.amount)
|
||||
self.incr += 1
|
||||
|
||||
|
||||
def get_sid_filter(self):
|
||||
return [self.sid]
|
||||
|
||||
return [self.sid]
|
||||
|
||||
class NoopAlgorithm(object):
|
||||
"""
|
||||
Dolce fa niente.
|
||||
"""
|
||||
|
||||
|
||||
def initialize(self):
|
||||
pass
|
||||
|
||||
|
||||
def set_order(self, order_callable):
|
||||
pass
|
||||
|
||||
|
||||
def set_portfolio(self, portfolio):
|
||||
pass
|
||||
|
||||
|
||||
def handle_data(self, data):
|
||||
pass
|
||||
|
||||
|
||||
def get_sid_filter(self):
|
||||
return None
|
||||
return None
|
||||
|
||||
@@ -20,7 +20,6 @@ class BaseTransform(Component):
|
||||
Parent class for feed transforms. Subclass and override transform
|
||||
method to create a new derived value from the combined feed.
|
||||
"""
|
||||
|
||||
def init(self):
|
||||
pass
|
||||
|
||||
|
||||
@@ -57,13 +57,13 @@ def iso8061_to_epoch(datestring):
|
||||
return EPOCH(dt)
|
||||
|
||||
def epoch_now():
|
||||
dt = datetime.utcnow().replace(tzinfo=pytz.utc)
|
||||
dt = utcnow()
|
||||
return EPOCH(dt)
|
||||
|
||||
# UTC Datetime Subclasses
|
||||
# -----------------------
|
||||
def utcnow():
|
||||
return datetime.now(pytz.utc)
|
||||
return datetime.utcnow().replace(tzinfo=pytz.utc)
|
||||
|
||||
class utcdatetime(datetime):
|
||||
def __new__(cls, *args, **kwargs):
|
||||
|
||||
Reference in New Issue
Block a user