Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
fredfortier committed Feb 8, 2018
2 parents 43a5f88 + 09ad397 commit 403d7f9
Show file tree
Hide file tree
Showing 7 changed files with 452 additions and 45 deletions.
6 changes: 3 additions & 3 deletions catalyst/examples/buy_low_sell_high.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def _handle_data(context, data):
rsi=rsi,
)

orders = get_open_orders(context.asset)
orders = context.blotter.open_orders
if orders:
log.info('skipping bar until all open orders execute')
return
Expand Down Expand Up @@ -146,11 +146,11 @@ def analyze(context, stats):
live = True
if live:
run_algorithm(
capital_base=0.001,
capital_base=1000,
initialize=initialize,
handle_data=handle_data,
analyze=analyze,
exchange_name='binance',
exchange_name='bittrex',
live=True,
algo_namespace=algo_namespace,
base_currency='btc',
Expand Down
63 changes: 38 additions & 25 deletions catalyst/examples/dual_moving_average.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ def initialize(context):

def handle_data(context, data):
# define the windows for the moving averages
short_window = 50
long_window = 200
short_window = 2
long_window = 2

# Skip as many bars as long_window to properly compute the average
context.i += 1
Expand All @@ -32,16 +32,18 @@ def handle_data(context, data):
# moving average with the appropriate parameters. We choose to use
# minute bars for this simulation -> freq="1m"
# Returns a pandas dataframe.
short_mavg = data.history(context.asset,
short_data = data.history(context.asset,
'price',
bar_count=short_window,
frequency="1m",
).mean()
long_mavg = data.history(context.asset,
frequency="1T",
)
short_mavg = short_data.mean()
long_data = data.history(context.asset,
'price',
bar_count=long_window,
frequency="1m",
).mean()
frequency="1T",
)
long_mavg = long_data.mean()

# Let's keep the price of our asset in a more handy variable
price = data.current(context.asset, 'price')
Expand Down Expand Up @@ -82,7 +84,6 @@ def handle_data(context, data):


def analyze(context, perf):

# Get the base_currency that was passed as a parameter to the simulation
exchange = list(context.exchanges.values())[0]
base_currency = exchange.base_currency.upper()
Expand All @@ -93,7 +94,7 @@ def analyze(context, perf):
ax1.legend_.remove()
ax1.set_ylabel('Portfolio Value\n({})'.format(base_currency))
start, end = ax1.get_ylim()
ax1.yaxis.set_ticks(np.arange(start, end, (end-start)/5))
ax1.yaxis.set_ticks(np.arange(start, end, (end - start) / 5))

# Second chart: Plot asset price, moving averages and buys/sells
ax2 = plt.subplot(412, sharex=ax1)
Expand All @@ -104,9 +105,9 @@ def analyze(context, perf):
ax2.set_ylabel('{asset}\n({base})'.format(
asset=context.asset.symbol,
base=base_currency
))
))
start, end = ax2.get_ylim()
ax2.yaxis.set_ticks(np.arange(start, end, (end-start)/5))
ax2.yaxis.set_ticks(np.arange(start, end, (end - start) / 5))

transaction_df = extract_transactions(perf)
if not transaction_df.empty:
Expand Down Expand Up @@ -136,28 +137,40 @@ def analyze(context, perf):
ax3.legend_.remove()
ax3.set_ylabel('Percent Change')
start, end = ax3.get_ylim()
ax3.yaxis.set_ticks(np.arange(start, end, (end-start)/5))
ax3.yaxis.set_ticks(np.arange(start, end, (end - start) / 5))

# Fourth chart: Plot our cash
ax4 = plt.subplot(414, sharex=ax1)
perf.cash.plot(ax=ax4)
ax4.set_ylabel('Cash\n({})'.format(base_currency))
start, end = ax4.get_ylim()
ax4.yaxis.set_ticks(np.arange(0, end, end/5))
ax4.yaxis.set_ticks(np.arange(0, end, end / 5))

plt.show()


if __name__ == '__main__':
run_algorithm(
capital_base=1000,
data_frequency='minute',
initialize=initialize,
handle_data=handle_data,
analyze=analyze,
exchange_name='bitfinex',
algo_namespace=NAMESPACE,
base_currency='usd',
start=pd.to_datetime('2017-9-22', utc=True),
end=pd.to_datetime('2017-9-23', utc=True),
)
capital_base=1000,
data_frequency='minute',
initialize=initialize,
handle_data=handle_data,
analyze=analyze,
exchange_name='bitfinex',
algo_namespace=NAMESPACE,
base_currency='usd',
simulate_orders=True,
live=True,
)
# run_algorithm(
# capital_base=1000,
# data_frequency='minute',
# initialize=initialize,
# handle_data=handle_data,
# analyze=analyze,
# exchange_name='bitfinex',
# algo_namespace=NAMESPACE,
# base_currency='usd',
# start=pd.to_datetime('2017-9-22', utc=True),
# end=pd.to_datetime('2017-9-23', utc=True),
# )
20 changes: 10 additions & 10 deletions catalyst/exchange/ccxt/ccxt_exchange.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,26 +425,26 @@ def get_candles(self, freq, assets, bar_count=1, start_dt=None,
'Please provide either start_dt or end_dt, not both.'
)

elif end_dt is not None:
# Make sure that end_dt really wants data in the past
# if it's close to now, we skip the 'since' parameters to
# lower the probability of error
bars_to_now = pd.date_range(
end_dt, pd.Timestamp.utcnow(), freq=freq
)
# See: https://github.com/ccxt/ccxt/issues/1360
if len(bars_to_now) > 1 or self.name in ['poloniex']:
if start_dt is None:
# TODO: determine why binance is failing
if end_dt is None and self.name not in ['binance']:
end_dt = pd.Timestamp.utcnow()

if end_dt is not None:
dt_range = get_periods_range(
end_dt=end_dt,
periods=bar_count,
freq=freq,
)
start_dt = dt_range[0]

since = None
if start_dt is not None:
# Convert out start date to a UNIX timestamp, then translate to
# milliseconds
delta = start_dt - get_epoch()
since = int(delta.total_seconds()) * 1000
else:
since = None

candles = dict()
for index, asset in enumerate(assets):
Expand Down
10 changes: 8 additions & 2 deletions catalyst/exchange/exchange_algorithm.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,8 +391,6 @@ def __init__(self, *args, **kwargs):
log.warn("Can't initialize signal handler inside another thread."
"Exit should be handled by the user.")

log.info('initialized trading algorithm in live mode')

def interrupt_algorithm(self):
self.is_running = False

Expand Down Expand Up @@ -874,6 +872,13 @@ def batch_market_order(self, share_counts):
raise NotImplementedError()

def _get_open_orders(self, asset=None):
if self.simulate_orders:
raise ValueError(
'The get_open_orders() method only works in live mode. '
'The purpose is to list open orders on the exchange '
'regardless who placed them. To list the open orders of '
'this algo, use `context.blotter.open_orders`.'
)
if asset:
exchange = self.exchanges[asset.exchange]
return exchange.get_open_orders(asset)
Expand Down Expand Up @@ -907,6 +912,7 @@ def get_open_orders(self, asset=None):
If an asset is passed then this will return a list of the open
orders for this asset.
"""
# TODO: should this be a shortcut to the open orders in the blotter?
return retry(
action=self._get_open_orders,
attempts=self.attempts['get_open_orders_attempts'],
Expand Down
Loading

0 comments on commit 403d7f9

Please sign in to comment.