Merge pull request #60 from quantopian/optimize_qexec

Optimization fixes and more refactoring
This commit is contained in:
Stephen Diehl
2012-05-30 07:42:51 -07:00
3 changed files with 82 additions and 48 deletions
+13 -40
View File
@@ -1,23 +1,15 @@
"""Tests for the zipline.finance package"""
import unittest
from unittest2 import TestCase, skip
from nose.tools import timed
from collections import defaultdict
from datetime import datetime, timedelta
import logging
import numpy as np
from zipline.optimize.factory import create_updown_trade_source
import zipline.utils.factory as factory
from zipline.utils.logger import configure_logging
from zipline.core.devsimulator import AddressAllocator, Simulator
from zipline.optimize.algorithms import BuySellAlgorithm
from zipline.core.devsimulator import AddressAllocator
from zipline.optimize.factory import create_predictable_zipline
from zipline.finance.trading import TradingEnvironment
from zipline.lines import SimulatedTrading
from zipline.finance.trading import SIMULATION_STYLE
DEFAULT_TIMEOUT = 15 # seconds
EXTENDED_TIMEOUT = 90
@@ -37,7 +29,10 @@ class TestUpDown(TestCase):
configure_logging()
self.zipline_test_config = {
'allocator':allocator,
'sid':133
'sid':133,
'trade_count':5,
'amplitude':30,
'base_price':50
}
@timed(DEFAULT_TIMEOUT)
@@ -48,23 +43,16 @@ class TestUpDown(TestCase):
UpDownSource and BuySellAlgorithm interact correctly."
"""
#generate events
trade_count = 5
sid = 133
base_price = 50
amplitude = 6
offset = 0
zipline, config = create_predictable_zipline(
self.zipline_test_config,
sid=sid,
amplitude=amplitude,
base_price=base_price,
offset=offset,
trade_count=5,
offset=0,
simulate=False
)
#extract arguments
base_price = self.zipline_test_config['base_price']
amplitude = self.zipline_test_config['amplitude']
prices = np.array([event.price for event in config['trade_source'].event_list])
max_price_idx = np.where(prices==prices.max())[0]
min_price_idx = np.where(prices==prices.min())[0]
@@ -109,14 +97,9 @@ class TestUpDown(TestCase):
(i.e. 0).
"""
#generate events
trade_count = 6
sid = 133
amplitude = 30
base_price = 50
#test whether return-function is concave wrt repeats.
test_offsets = np.arange(-9, 9, 1.)
#maximum value is expect to be at center, create boolean mask
#for later extraction
supposed_max = np.zeros(len(test_offsets), dtype=bool)
supposed_max[len(test_offsets) // 2] = True
@@ -125,12 +108,7 @@ class TestUpDown(TestCase):
for i, offset in enumerate(test_offsets):
zipline, config = create_predictable_zipline(
self.zipline_test_config,
sid=sid,
amplitude=amplitude,
base_price=base_price,
offset=offset,
trade_count=trade_count,
simulate=True
)
ziplines.append(zipline)
compound_returns[i] = zipline.get_cumulative_performance()['returns']
@@ -153,7 +131,7 @@ class TestUpDown(TestCase):
idx[0] -= 1
idx[1] += 1
#@skip
@skip
def test_optimize(self):
"""verify that gradient descent (Powell's method) can find
the optimal free parameter under which the BuySellAlgorithm produces
@@ -163,12 +141,7 @@ class TestUpDown(TestCase):
def simulate(offset):
zipline, config = create_predictable_zipline(
self.zipline_test_config,
sid=133,
amplitude=10,
base_price=50,
offset=offset,
trade_count=5,
simulate=True
)
#function is getting minimized, so have to return negative cum returns.
return -zipline.get_cumulative_performance()['returns']
+1 -2
View File
@@ -1,4 +1,4 @@
class BuySellAlgorithm():
class BuySellAlgorithm(object):
"""Algorithm that buys and sells alternatingly. The amount for
each order can be specified. In addition, an offset that will
quadratically reduce the amount that will be bought can be
@@ -40,7 +40,6 @@ class BuySellAlgorithm():
self.buy_or_sell *= -1
self.orders.append(order_size)
#self.prices.append(frame['price'])
self.frame_count += 1
self.incr += 1
+68 -6
View File
@@ -3,7 +3,7 @@ Factory functions to prepare useful data for optimize tests.
Author: Thomas V. Wiecki (thomas.wiecki@gmail.com), 2012
"""
from datetime import datetime, timedelta
from datetime import timedelta
import zipline.protocol as zp
@@ -13,13 +13,34 @@ from zipline.optimize.algorithms import BuySellAlgorithm
from zipline.lines import SimulatedTrading
from zipline.finance.trading import SIMULATION_STYLE
from copy import deepcopy
from copy import copy
from itertools import cycle
def create_updown_trade_source(sid, trade_count, trading_environment, start_price, amplitude):
def create_updown_trade_source(sid, trade_count, trading_environment, base_price, amplitude):
"""Create the updown trade source. This source emits events with
the price going up and down by the same amount in each
iteration. The trade source is thus perfectly predictable. This is
used for a test case for the optimization code.
:Arguments:
sid : int
SID of stock to create.
trade_count : int
How many trade events to create (will also influence order count)
trading_environment : TradeEnvironment object
The trading environment to use (see zipline.factory.create_trading_environment)
base_price : int
The average price that each iteration will hover around.
amplitude : int
How much the price will go up and down each iteration.
:Returns:
source : SpecificEquityTrades
The trade source emitting up down events.
"""
volume = 1000
events = []
price = start_price-amplitude/2.
price = base_price-amplitude/2.
cur = trading_environment.first_open
one_day = timedelta(days = 1)
@@ -49,8 +70,49 @@ def create_updown_trade_source(sid, trade_count, trading_environment, start_pric
return source
def create_predictable_zipline(config, sid=133, amplitude=10, base_price=50, offset=0, trade_count=3, simulate=True):
#config = deepcopy(config)
def create_predictable_zipline(config, offset=0, simulate=True):
"""Create a test zipline object as specified by config. The
zipline will use the UpDown tradesource which is perfectly
predictable.
Trade source parameters can be specified inside the config object.
:Trade source arguments:
config['sid'] : int
SID of stock to create.
config['amplitude'] : int (default 10)
How much the price will go up and down each iteration.
config['base_price'] : int (default 50)
The average price that each iteration will hover around.
config['trade_count'] : int (default 3)
How many trade events to create (will also influence order count)
If not specified, the BuySellAlgorithm is used by default. This
can be changed by setting config['algorithm'].
:Arguments:
offset : int (default 0)
The offset parameter specifies how much the BuySellAlgorithm will
order each iteration and is a negative quadratic centered around
0. Thus, any deviations from 0 will lead to less buy and sell
orders each iteration and ultimately to less compound returns.
simulate : bool (default True)
Whether to call .simulate(blocking=True) on the created zipline
argument.
:Returns:
zipline : class zipline
created zipline object
config : dict
the config dict used to create the zipline
"""
config = copy(config)
sid = config['sid']
# remove
amplitude = config.pop('amplitude', 10)
base_price = config.pop('base_price', 50)
trade_count = config.pop('trade_count', 3)
trading_environment = create_trading_environment()
source = create_updown_trade_source(sid,
trade_count,