BLD: for issue #87, added configurable slippage and commission

This commit is contained in:
Frederic Fortier
2017-12-11 22:34:46 -05:00
parent 0c3b5fc3c5
commit 552f4260b4
3 changed files with 48 additions and 25 deletions
@@ -44,6 +44,9 @@ def initialize(context):
context.start_time = time.time()
# context.set_commission(maker=0.1, taker=0.2)
context.set_slippage(spread=0.0001)
def handle_data(context, data):
# This handle_data function is where the real work is done. Our data is
+16
View File
@@ -23,6 +23,7 @@ import pandas as pd
import catalyst.protocol as zp
from catalyst.algorithm import TradingAlgorithm
from catalyst.assets._assets import TradingPair
from catalyst.constants import LOG_LEVEL
from catalyst.exchange.exchange_blotter import ExchangeBlotter
from catalyst.exchange.exchange_errors import (
@@ -113,6 +114,21 @@ class ExchangeTradingAlgorithmBase(TradingAlgorithm):
else:
return MarketOrder()
@api_method
def set_commission(self, maker=None, taker=None):
key = self.blotter.commission_models.keys()[0]
if maker is not None:
self.blotter.commission_models[key].maker = maker
if taker is not None:
self.blotter.commission_models[key].taker = taker
@api_method
def set_slippage(self, spread=None):
key = self.blotter.slippage_models.keys()[0]
if spread is not None:
self.blotter.slippage_models[key].spread = spread
def _calculate_order(self, asset, amount,
limit_price=None, stop_price=None, style=None):
# Raises a ZiplineError if invalid parameters are detected.
+29 -25
View File
@@ -9,20 +9,13 @@ from catalyst.exchange.exchange_errors import ExchangeRequestError, \
ExchangePortfolioDataError, ExchangeTransactionError
from catalyst.finance.blotter import Blotter
from catalyst.finance.commission import CommissionModel
from catalyst.finance.order import ORDER_STATUS
from catalyst.finance.order import ORDER_STATUS, Order
from catalyst.finance.slippage import SlippageModel
from catalyst.finance.transaction import create_transaction, Transaction
from catalyst.utils.input_validation import expect_types
log = Logger('exchange_blotter', level=LOG_LEVEL)
# It seems like we need to accept greater slippage risk in cryptos
# Orders won't often close at Equity levels.
# TODO: should work with set_commission and set_slippage
DEFAULT_SLIPPAGE_SPREAD = 0.0001
DEFAULT_MAKER_FEE = 0.0015
DEFAULT_TAKER_FEE = 0.0025
class TradingPairFeeSchedule(CommissionModel):
"""
@@ -30,23 +23,24 @@ class TradingPairFeeSchedule(CommissionModel):
Parameters
----------
fee : float, optional
The percentage fee.
maker : float, optional
The percentage maker fee.
taker: float, optional
The percentage taker fee.
"""
def __init__(self,
maker_fee=DEFAULT_MAKER_FEE,
taker_fee=DEFAULT_TAKER_FEE):
self.maker_fee = maker_fee
self.taker_fee = taker_fee
def __init__(self, maker=None, taker=None):
self.maker = maker
self.taker = taker
def __repr__(self):
return (
'{class_name}(maker_fee={maker_fee}, '
'taker_fee={taker_fee})'.format(
'{class_name}(maker={maker}, '
'taker={taker})'.format(
class_name=self.__class__.__name__,
maker_fee=self.maker_fee,
taker_fee=self.taker_fee,
maker=self.maker,
taker=self.taker,
)
)
@@ -54,16 +48,25 @@ class TradingPairFeeSchedule(CommissionModel):
"""
Calculate the final fee based on the order parameters.
:param order:
:param transaction:
:param order: Order
:param transaction: Transaction
:return float:
The total commission.
"""
cost = abs(transaction.amount) * transaction.price
asset = order.asset
maker = self.maker if self.maker is not None else asset.maker
taker = self.taker if self.taker is not None else asset.taker
multiplier = maker \
if ((order.amount > 0 and order.limit < transaction.price)
or (order.amount < 0 and order.limit > transaction.price)) \
and order.limit_reached else taker
# Assuming just the taker fee for now
fee = cost * self.taker_fee
fee = cost * multiplier
return fee
@@ -77,7 +80,7 @@ class TradingPairFixedSlippage(SlippageModel):
spread / 2 will be added to buys and subtracted from sells.
"""
def __init__(self, spread=DEFAULT_SLIPPAGE_SPREAD):
def __init__(self, spread=0.0001):
super(TradingPairFixedSlippage, self).__init__()
self.spread = spread
@@ -132,8 +135,9 @@ class ExchangeBlotter(Blotter):
self.exchanges = kwargs.pop('exchanges', None)
if not self.exchanges:
raise ValueError('ExchangeBlotter must have an `exchanges` '
'attribute.')
raise ValueError(
'ExchangeBlotter must have an `exchanges` attribute.'
)
super(ExchangeBlotter, self).__init__(*args, **kwargs)