mirror of
https://github.com/wassname/catalyst.git
synced 2026-08-11 11:16:15 +08:00
BLD: for issue #87, added configurable slippage and commission
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user