mirror of
https://github.com/wassname/catalyst.git
synced 2026-06-30 05:55:30 +08:00
ENH: Extended commission PerShare method to allow a minimum cost per trade.
Also added unit tests (test_perf_tracking.TestCommissionEvents) to test all commission models.
This commit is contained in:
committed by
Eddie Hebert
parent
ae4a9b7d96
commit
011ed09dc2
@@ -33,6 +33,7 @@ import zipline.utils.math_utils as zp_math
|
||||
from zipline.gens.composites import date_sorted_sources
|
||||
from zipline.finance.trading import SimulationParameters
|
||||
from zipline.finance.blotter import Order
|
||||
from zipline.finance.commission import PerShare, PerTrade, PerDollar
|
||||
from zipline.finance import trading
|
||||
from zipline.protocol import DATASOURCE_TYPE
|
||||
from zipline.utils.factory import create_random_simulation_parameters
|
||||
@@ -172,6 +173,29 @@ class TestCommissionEvents(unittest.TestCase):
|
||||
self.sim_params
|
||||
)
|
||||
|
||||
# Test commission models and validate result
|
||||
# Expected commission amounts:
|
||||
# PerShare commission: 1.00, 1.00, 1.50 = $3.50
|
||||
# PerTrade commission: 5.00, 5.00, 5.00 = $15.00
|
||||
# PerDollar commission: 1.50, 3.00, 4.50 = $9.00
|
||||
# Total commission = $3.50 + $15.00 + $9.00 = $27.50
|
||||
|
||||
# Create 3 transactions: 50, 100, 150 shares traded @ $20
|
||||
transactions = [create_txn(events[0], 20, i)
|
||||
for i in [50, 100, 150]]
|
||||
|
||||
# Create commission models
|
||||
models = [PerShare(cost=0.01, min_trade_cost=1.00),
|
||||
PerTrade(cost=5.00),
|
||||
PerDollar(cost=0.0015)]
|
||||
|
||||
# Aggregate commission amounts
|
||||
total_commission = 0
|
||||
for model in models:
|
||||
for trade in transactions:
|
||||
total_commission += model.calculate(trade)[1]
|
||||
self.assertEqual(total_commission, 27.5)
|
||||
|
||||
cash_adj_dt = self.sim_params.first_open \
|
||||
+ datetime.timedelta(hours=3)
|
||||
cash_adjustment = factory.create_commission(1, 300.0,
|
||||
|
||||
@@ -17,28 +17,38 @@
|
||||
class PerShare(object):
|
||||
"""
|
||||
Calculates a commission for a transaction based on a per
|
||||
share cost.
|
||||
share cost with an optional minimum cost per trade.
|
||||
"""
|
||||
|
||||
def __init__(self, cost=0.03):
|
||||
def __init__(self, cost=0.03, min_trade_cost=None):
|
||||
"""
|
||||
Cost parameter is the cost of a trade per-share. $0.03
|
||||
means three cents per share, which is a very conservative
|
||||
(quite high) for per share costs.
|
||||
min_trade_cost parameter is the minimum trade cost
|
||||
regardless of the number of shares traded (e.g. $1.00).
|
||||
"""
|
||||
self.cost = float(cost)
|
||||
self.min_trade_cost = None if min_trade_cost is None\
|
||||
else float(min_trade_cost)
|
||||
|
||||
def __repr__(self):
|
||||
return "{class_name}(cost={cost})".format(
|
||||
class_name=self.__class__.__name__,
|
||||
cost=self.cost)
|
||||
return "{class_name}(cost={cost}, min trade cost={min_trade_cost})"\
|
||||
.format(class_name=self.__class__.__name__,
|
||||
cost=self.cost,
|
||||
min_trade_cost=self.min_trade_cost)
|
||||
|
||||
def calculate(self, transaction):
|
||||
"""
|
||||
returns a tuple of:
|
||||
(per share commission, total transaction commission)
|
||||
"""
|
||||
return self.cost, abs(transaction.amount * self.cost)
|
||||
commission = abs(transaction.amount * self.cost)
|
||||
if self.min_trade_cost is None:
|
||||
return self.cost, commission
|
||||
else:
|
||||
commission = max(commission, self.min_trade_cost)
|
||||
return abs(commission / transaction.amount), commission
|
||||
|
||||
|
||||
class PerTrade(object):
|
||||
|
||||
Reference in New Issue
Block a user