mirror of
https://github.com/wassname/catalyst.git
synced 2026-07-08 01:20:58 +08:00
Merge pull request #207 from quantopian/splits_fixes
fixing some bugs with splits (ratios and empty positions)
This commit is contained in:
@@ -422,6 +422,7 @@ class FinanceTestCase(TestCase):
|
||||
self.assertEqual(1, aapl_order['sid'])
|
||||
|
||||
# make sure the fls order did change
|
||||
self.assertEqual(33, fls_order['amount'])
|
||||
self.assertEqual(30, fls_order['limit'])
|
||||
# to 300 shares at 3.33
|
||||
self.assertEqual(300, fls_order['amount'])
|
||||
self.assertEqual(3.33, fls_order['limit'])
|
||||
self.assertEqual(2, fls_order['sid'])
|
||||
|
||||
@@ -110,7 +110,9 @@ class TestSplitPerformance(unittest.TestCase):
|
||||
# set up a long position in sid 1
|
||||
# 100 shares at $20 apiece = $2000 position
|
||||
events.insert(0, create_txn(events[0], 20, 100))
|
||||
events.append(factory.create_split(1, 0.33333,
|
||||
|
||||
# set up a split with ratio 3
|
||||
events.append(factory.create_split(1, 3,
|
||||
env.next_trading_day(events[1].dt)))
|
||||
|
||||
results = calculate_results(self, events)
|
||||
|
||||
@@ -255,16 +255,16 @@ class Order(object):
|
||||
# info here: http://finra.complinet.com/en/display/display_plain.html?
|
||||
# rbid=2403&element_id=8950&record_id=12208&print=1
|
||||
|
||||
# if we have an open order for 100 shares at $20, and we get
|
||||
# a 3:1 split, we now want to have an open order for 33 shares at $60
|
||||
# for the amount, we round down to the nearest whole share
|
||||
self.amount = int(self.amount * ratio)
|
||||
# new_share_amount = old_share_amount / ratio
|
||||
# new_price = old_price * ratio
|
||||
|
||||
self.amount = int(self.amount / ratio)
|
||||
|
||||
if self.limit:
|
||||
self.limit = round(self.limit / ratio, 2)
|
||||
self.limit = round(self.limit * ratio, 2)
|
||||
|
||||
if self.stop:
|
||||
self.stop = round(self.stop / ratio, 2)
|
||||
self.stop = round(self.stop * ratio, 2)
|
||||
|
||||
@property
|
||||
def open(self):
|
||||
|
||||
@@ -518,12 +518,18 @@ class Position(object):
|
||||
|
||||
ratio = split.ratio
|
||||
|
||||
log.info("handling split for sid = " + str(split.sid) +
|
||||
", ratio = " + str(split.ratio))
|
||||
log.info("before split: " + str(self))
|
||||
|
||||
# adjust the # of shares by the ratio
|
||||
# (if we had 100 shares, and the ratio is 0.33333,
|
||||
# (if we had 100 shares, and the ratio is 3,
|
||||
# we now have 33 shares)
|
||||
# (old_share_count / ratio = new_share_count)
|
||||
# (old_price * ratio = new_price)
|
||||
|
||||
# ie, 33.333
|
||||
raw_share_count = self.amount * ratio
|
||||
raw_share_count = self.amount / float(ratio)
|
||||
|
||||
# ie, 33
|
||||
full_share_count = math.floor(raw_share_count)
|
||||
@@ -532,18 +538,23 @@ class Position(object):
|
||||
fractional_share_count = raw_share_count - full_share_count
|
||||
|
||||
# adjust the cost basis to the nearest cent, ie, 60.0
|
||||
new_cost_basis = round(self.cost_basis / ratio, 2)
|
||||
new_cost_basis = round(self.cost_basis * ratio, 2)
|
||||
|
||||
# adjust the last sale price
|
||||
new_last_sale_price = round(self.last_sale_price / ratio, 2)
|
||||
new_last_sale_price = round(self.last_sale_price * ratio, 2)
|
||||
|
||||
self.cost_basis = new_cost_basis
|
||||
self.last_sale_price = new_last_sale_price
|
||||
self.amount = full_share_count
|
||||
|
||||
return_cash = round(float(fractional_share_count * new_cost_basis), 2)
|
||||
|
||||
log.info("after split: " + str(self))
|
||||
log.info("returning cash: " + str(return_cash))
|
||||
|
||||
# return the leftover cash, which will be converted into cash
|
||||
# (rounded to the nearest cent)
|
||||
return round(float(fractional_share_count * new_cost_basis), 2)
|
||||
return return_cash
|
||||
|
||||
def update(self, txn):
|
||||
if(self.sid != txn.sid):
|
||||
@@ -663,12 +674,13 @@ class PerformancePeriod(object):
|
||||
self.positions[div.sid].add_dividend(div)
|
||||
|
||||
def handle_split(self, split):
|
||||
# Make the position object handle the split. It returns the
|
||||
# leftover cash from a fractional share, if there is any.
|
||||
leftover_cash = self.positions[split.sid].handle_split(split)
|
||||
if split.sid in self.positions:
|
||||
# Make the position object handle the split. It returns the
|
||||
# leftover cash from a fractional share, if there is any.
|
||||
leftover_cash = self.positions[split.sid].handle_split(split)
|
||||
|
||||
if leftover_cash > 0:
|
||||
self.handle_cash_payment(leftover_cash)
|
||||
if leftover_cash > 0:
|
||||
self.handle_cash_payment(leftover_cash)
|
||||
|
||||
def update_dividends(self, todays_date):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user