mirror of
https://github.com/wassname/catalyst.git
synced 2026-09-09 11:19:23 +08:00
Compare commits
23
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
027cdba474 | ||
|
|
d223529100 | ||
|
|
1e02506ab4 | ||
|
|
2a97ade68e | ||
|
|
9648767e9a | ||
|
|
98449b2088 | ||
|
|
91d16aba3b | ||
|
|
b76b4458cb | ||
|
|
decbdbf6ea | ||
|
|
685ce25b85 | ||
|
|
1cafcc1417 | ||
|
|
0d77854782 | ||
|
|
4cb8d54d97 | ||
|
|
7b796a4276 | ||
|
|
41a4c7072f | ||
|
|
11302b3af9 | ||
|
|
5bb7eed072 | ||
|
|
dbf3b6e6b2 | ||
|
|
3e69449a6b | ||
|
|
69731b653d | ||
|
|
127d779eb1 | ||
|
|
8d86a5548f | ||
|
|
0a37cdec5b |
@@ -793,7 +793,7 @@ def ls(ctx):
|
|||||||
)
|
)
|
||||||
@click.pass_context
|
@click.pass_context
|
||||||
def subscribe(ctx, dataset):
|
def subscribe(ctx, dataset):
|
||||||
"""Subscribe to an exisiting dataset.
|
"""Subscribe to an existing dataset.
|
||||||
"""
|
"""
|
||||||
marketplace = Marketplace()
|
marketplace = Marketplace()
|
||||||
marketplace.subscribe(dataset)
|
marketplace.subscribe(dataset)
|
||||||
|
|||||||
@@ -25,8 +25,7 @@ AUTO_INGEST = False
|
|||||||
AUTH_SERVER = 'https://data.enigma.co'
|
AUTH_SERVER = 'https://data.enigma.co'
|
||||||
|
|
||||||
# TODO: switch to mainnet
|
# TODO: switch to mainnet
|
||||||
ETH_REMOTE_NODE = 'https://ropsten.infura.io/'
|
ETH_REMOTE_NODE = 'https://rinkeby.infura.io/'
|
||||||
|
|
||||||
|
|
||||||
MARKETPLACE_CONTRACT = 'https://raw.githubusercontent.com/enigmampc/' \
|
MARKETPLACE_CONTRACT = 'https://raw.githubusercontent.com/enigmampc/' \
|
||||||
'catalyst/master/catalyst/marketplace/' \
|
'catalyst/master/catalyst/marketplace/' \
|
||||||
@@ -37,8 +36,8 @@ MARKETPLACE_CONTRACT_ABI = 'https://raw.githubusercontent.com/enigmampc/' \
|
|||||||
'contract_marketplace_abi.json'
|
'contract_marketplace_abi.json'
|
||||||
|
|
||||||
# TODO: switch to mainnet
|
# TODO: switch to mainnet
|
||||||
ENIGMA_CONTRACT = 'https://raw.githubusercontent.com/enigmampc/catalyst/' \
|
ENIGMA_CONTRACT = 'https://raw.githubusercontent.com/enigmampc/' \
|
||||||
'master/catalyst/marketplace/' \
|
'catalyst/master/catalyst/marketplace/' \
|
||||||
'contract_enigma_address.txt'
|
'contract_enigma_address.txt'
|
||||||
|
|
||||||
ENIGMA_CONTRACT_ABI = 'https://raw.githubusercontent.com/enigmampc/' \
|
ENIGMA_CONTRACT_ABI = 'https://raw.githubusercontent.com/enigmampc/' \
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ def handle_data(context, data):
|
|||||||
context.asset,
|
context.asset,
|
||||||
fields='price',
|
fields='price',
|
||||||
bar_count=20,
|
bar_count=20,
|
||||||
frequency='2H'
|
frequency='30T'
|
||||||
)
|
)
|
||||||
last_traded = prices.index[-1]
|
last_traded = prices.index[-1]
|
||||||
log.info('last candle date: {}'.format(last_traded))
|
log.info('last candle date: {}'.format(last_traded))
|
||||||
|
|||||||
@@ -190,6 +190,9 @@ class CCXT(Exchange):
|
|||||||
if data_frequency == 'minute' and not freq.endswith('T'):
|
if data_frequency == 'minute' and not freq.endswith('T'):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
elif data_frequency == 'hourly' and not freq.endswith('D'):
|
||||||
|
continue
|
||||||
|
|
||||||
elif data_frequency == 'daily' and not freq.endswith('D'):
|
elif data_frequency == 'daily' and not freq.endswith('D'):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ from catalyst.exchange.exchange_errors import MismatchingBaseCurrencies, \
|
|||||||
TickerNotFoundError, NotEnoughCashError
|
TickerNotFoundError, NotEnoughCashError
|
||||||
from catalyst.exchange.utils.datetime_utils import get_delta, \
|
from catalyst.exchange.utils.datetime_utils import get_delta, \
|
||||||
get_periods_range, \
|
get_periods_range, \
|
||||||
get_periods, get_start_dt, get_frequency
|
get_periods, get_start_dt, get_frequency, \
|
||||||
|
get_candles_number_from_minutes
|
||||||
from catalyst.exchange.utils.exchange_utils import get_exchange_symbols, \
|
from catalyst.exchange.utils.exchange_utils import get_exchange_symbols, \
|
||||||
resample_history_df, has_bundle, get_candles_df
|
resample_history_df, has_bundle, get_candles_df
|
||||||
from logbook import Logger
|
from logbook import Logger
|
||||||
@@ -511,7 +512,12 @@ class Exchange:
|
|||||||
# so we request more than needed
|
# so we request more than needed
|
||||||
# TODO: consider defining a const per asset
|
# TODO: consider defining a const per asset
|
||||||
# and/or some retry mechanism (in each iteration request more data)
|
# and/or some retry mechanism (in each iteration request more data)
|
||||||
requested_bar_count = bar_count + 30
|
kExtra_minutes_candles = 150
|
||||||
|
requested_bar_count = bar_count + \
|
||||||
|
get_candles_number_from_minutes(unit,
|
||||||
|
candle_size,
|
||||||
|
kExtra_minutes_candles)
|
||||||
|
|
||||||
# The get_history method supports multiple asset
|
# The get_history method supports multiple asset
|
||||||
candles = self.get_candles(
|
candles = self.get_candles(
|
||||||
freq=freq,
|
freq=freq,
|
||||||
@@ -529,11 +535,14 @@ class Exchange:
|
|||||||
asset=asset,
|
asset=asset,
|
||||||
exchange=self.name)
|
exchange=self.name)
|
||||||
|
|
||||||
|
# for avoiding unnecessary forward fill end_dt is taken back one second
|
||||||
|
forward_fill_till_dt = end_dt - timedelta(seconds=1)
|
||||||
|
|
||||||
series = get_candles_df(candles=candles,
|
series = get_candles_df(candles=candles,
|
||||||
field=field,
|
field=field,
|
||||||
freq=frequency,
|
freq=frequency,
|
||||||
bar_count=requested_bar_count,
|
bar_count=requested_bar_count,
|
||||||
end_dt=end_dt)
|
end_dt=forward_fill_till_dt)
|
||||||
|
|
||||||
# TODO: consider how to approach this edge case
|
# TODO: consider how to approach this edge case
|
||||||
# delta_candle_size = candle_size * 60 if unit == 'H' else candle_size
|
# delta_candle_size = candle_size * 60 if unit == 'H' else candle_size
|
||||||
@@ -602,7 +611,7 @@ class Exchange:
|
|||||||
# TODO: this function needs some work,
|
# TODO: this function needs some work,
|
||||||
# we're currently using it just for benchmark data
|
# we're currently using it just for benchmark data
|
||||||
freq, candle_size, unit, data_frequency = get_frequency(
|
freq, candle_size, unit, data_frequency = get_frequency(
|
||||||
frequency, data_frequency
|
frequency, data_frequency, supported_freqs=['T', 'D']
|
||||||
)
|
)
|
||||||
adj_bar_count = candle_size * bar_count
|
adj_bar_count = candle_size * bar_count
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -296,7 +296,7 @@ class DataPortalExchangeBacktest(DataPortalExchangeBase):
|
|||||||
bundle = self.exchange_bundles[exchange_name] # type: ExchangeBundle
|
bundle = self.exchange_bundles[exchange_name] # type: ExchangeBundle
|
||||||
|
|
||||||
freq, candle_size, unit, adj_data_frequency = get_frequency(
|
freq, candle_size, unit, adj_data_frequency = get_frequency(
|
||||||
frequency, data_frequency
|
frequency, data_frequency, supported_freqs=['T', 'D']
|
||||||
)
|
)
|
||||||
adj_bar_count = candle_size * bar_count
|
adj_bar_count = candle_size * bar_count
|
||||||
|
|
||||||
@@ -312,7 +312,7 @@ class DataPortalExchangeBacktest(DataPortalExchangeBase):
|
|||||||
algo_end_dt=self._last_available_session,
|
algo_end_dt=self._last_available_session,
|
||||||
)
|
)
|
||||||
|
|
||||||
start_dt = get_start_dt(end_dt, adj_bar_count, data_frequency)
|
start_dt = get_start_dt(end_dt, adj_bar_count, adj_data_frequency)
|
||||||
df = resample_history_df(pd.DataFrame(series), freq, field, start_dt)
|
df = resample_history_df(pd.DataFrame(series), freq, field, start_dt)
|
||||||
return df
|
return df
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import calendar
|
import calendar
|
||||||
|
import math
|
||||||
import re
|
import re
|
||||||
from datetime import datetime, timedelta, date
|
from datetime import datetime, timedelta, date
|
||||||
|
|
||||||
@@ -248,9 +249,12 @@ def get_year_start_end(dt, first_day=None, last_day=None):
|
|||||||
return year_start, year_end
|
return year_start, year_end
|
||||||
|
|
||||||
|
|
||||||
def get_frequency(freq, data_frequency=None, supported_freqs=['D', 'T']):
|
def get_frequency(freq, data_frequency=None, supported_freqs=['D', 'H', 'T']):
|
||||||
"""
|
"""
|
||||||
Get the frequency parameters.
|
Takes an arbitrary candle size (e.g. 15T) and converts to the lowest
|
||||||
|
common denominator supported by the data bundles (e.g. 1T). The data
|
||||||
|
bundles only support 1T and 1D frequencies. If another frequency
|
||||||
|
is requested, Catalyst must request the underlying data and resample.
|
||||||
|
|
||||||
Notes
|
Notes
|
||||||
-----
|
-----
|
||||||
@@ -305,14 +309,14 @@ def get_frequency(freq, data_frequency=None, supported_freqs=['D', 'T']):
|
|||||||
data_frequency = 'minute'
|
data_frequency = 'minute'
|
||||||
|
|
||||||
elif unit.lower() == 'h':
|
elif unit.lower() == 'h':
|
||||||
|
data_frequency = 'minute'
|
||||||
|
|
||||||
if 'H' in supported_freqs:
|
if 'H' in supported_freqs:
|
||||||
unit = 'H'
|
unit = 'H'
|
||||||
alias = '{}H'.format(candle_size)
|
alias = '{}H'.format(candle_size)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
candle_size = candle_size * 60
|
candle_size = candle_size * 60
|
||||||
alias = '{}T'.format(candle_size)
|
alias = '{}T'.format(candle_size)
|
||||||
data_frequency = 'minute'
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise InvalidHistoryFrequencyAlias(freq=freq)
|
raise InvalidHistoryFrequencyAlias(freq=freq)
|
||||||
@@ -326,3 +330,33 @@ def from_ms_timestamp(ms):
|
|||||||
|
|
||||||
def get_epoch():
|
def get_epoch():
|
||||||
return pd.to_datetime('1970-1-1', utc=True)
|
return pd.to_datetime('1970-1-1', utc=True)
|
||||||
|
|
||||||
|
|
||||||
|
def get_candles_number_from_minutes(unit, candle_size, minutes):
|
||||||
|
"""
|
||||||
|
Get the number of bars needed for the given time interval
|
||||||
|
in minutes.
|
||||||
|
|
||||||
|
Notes
|
||||||
|
-----
|
||||||
|
Supports only "T", "D" and "H" units
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
unit: str
|
||||||
|
candle_size : int
|
||||||
|
minutes: int
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
int
|
||||||
|
|
||||||
|
"""
|
||||||
|
if unit == "T":
|
||||||
|
res = (float(minutes) / candle_size)
|
||||||
|
elif unit == "H":
|
||||||
|
res = (minutes / 60.0) / candle_size
|
||||||
|
else: # unit == "D"
|
||||||
|
res = (minutes / 1440.0) / candle_size
|
||||||
|
|
||||||
|
return int(math.ceil(res))
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
0x7fAec9aaE31BE428DeAAE1be8195dF609079Fd10
|
0x39a54f480d922a58c963de8091a6c9afc69db2cf
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
0x3985f5de8fddf2e8f7705cd360b498bf35ebfbc4
|
0xa2b37c6cd52f60fd4eb46ca59fafcf22d081aebc
|
||||||
@@ -177,10 +177,12 @@ class Marketplace:
|
|||||||
def check_transaction(self, tx_hash):
|
def check_transaction(self, tx_hash):
|
||||||
|
|
||||||
if 'ropsten' in ETH_REMOTE_NODE:
|
if 'ropsten' in ETH_REMOTE_NODE:
|
||||||
etherscan = 'https://ropsten.etherscan.io/tx/{}'.format(
|
etherscan = 'https://ropsten.etherscan.io/tx/'
|
||||||
tx_hash)
|
elif 'rinkeby' in ETH_REMOTE_NODE:
|
||||||
|
etherscan = 'https://rinkeby.etherscan.io/tx/'
|
||||||
else:
|
else:
|
||||||
etherscan = 'https://etherscan.io/tx/{}'.format(tx_hash)
|
etherscan = 'https://etherscan.io/tx/'
|
||||||
|
etherscan = '{}{}'.format(etherscan, tx_hash)
|
||||||
|
|
||||||
print('\nYou can check the outcome of your transaction here:\n'
|
print('\nYou can check the outcome of your transaction here:\n'
|
||||||
'{}\n\n'.format(etherscan))
|
'{}\n\n'.format(etherscan))
|
||||||
@@ -329,9 +331,6 @@ class Marketplace:
|
|||||||
'nonce': self.web3.eth.getTransactionCount(address)}
|
'nonce': self.web3.eth.getTransactionCount(address)}
|
||||||
)
|
)
|
||||||
|
|
||||||
if 'ropsten' in ETH_REMOTE_NODE:
|
|
||||||
tx['gas'] = min(int(tx['gas'] * 1.5), 4700000)
|
|
||||||
|
|
||||||
signed_tx = self.sign_transaction(tx)
|
signed_tx = self.sign_transaction(tx)
|
||||||
try:
|
try:
|
||||||
tx_hash = '0x{}'.format(
|
tx_hash = '0x{}'.format(
|
||||||
@@ -371,9 +370,6 @@ class Marketplace:
|
|||||||
'from': address,
|
'from': address,
|
||||||
'nonce': self.web3.eth.getTransactionCount(address)})
|
'nonce': self.web3.eth.getTransactionCount(address)})
|
||||||
|
|
||||||
if 'ropsten' in ETH_REMOTE_NODE:
|
|
||||||
tx['gas'] = min(int(tx['gas'] * 1.5), 4700000)
|
|
||||||
|
|
||||||
signed_tx = self.sign_transaction(tx)
|
signed_tx = self.sign_transaction(tx)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -701,9 +697,6 @@ class Marketplace:
|
|||||||
'nonce': self.web3.eth.getTransactionCount(address)}
|
'nonce': self.web3.eth.getTransactionCount(address)}
|
||||||
)
|
)
|
||||||
|
|
||||||
if 'ropsten' in ETH_REMOTE_NODE:
|
|
||||||
tx['gas'] = min(int(tx['gas'] * 1.5), 4700000)
|
|
||||||
|
|
||||||
signed_tx = self.sign_transaction(tx)
|
signed_tx = self.sign_transaction(tx)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import hashlib
|
import hashlib
|
||||||
import hmac
|
import hmac
|
||||||
|
import webbrowser
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
import time
|
import time
|
||||||
@@ -45,10 +46,17 @@ def get_key_secret(pubAddr, wallet='mew'):
|
|||||||
nonce = '0x{}'.format(d['nonce'])
|
nonce = '0x{}'.format(d['nonce'])
|
||||||
|
|
||||||
if wallet == 'mew':
|
if wallet == 'mew':
|
||||||
|
url = 'https://www.myetherwallet.com/signmsg.html'
|
||||||
|
|
||||||
print('\nObtaining a key/secret pair to streamline all future '
|
print('\nObtaining a key/secret pair to streamline all future '
|
||||||
'requests with the authentication server.\n'
|
'requests with the authentication server.\n'
|
||||||
'Visit https://www.myetherwallet.com/signmsg.html and sign the '
|
'Visit {url} and sign the '
|
||||||
'following message:\n{}'.format(nonce))
|
'following message:\n{nonce}'.format(
|
||||||
|
url=url,
|
||||||
|
nonce=nonce))
|
||||||
|
|
||||||
|
webbrowser.open_new(url)
|
||||||
|
|
||||||
signature = input('Copy and Paste the "sig" field from '
|
signature = input('Copy and Paste the "sig" field from '
|
||||||
'the signature here (without the double quotes, '
|
'the signature here (without the double quotes, '
|
||||||
'only the HEX value):\n')
|
'only the HEX value):\n')
|
||||||
|
|||||||
@@ -88,5 +88,7 @@ def safely_reduce_dtype(ser): # pandas.Series or numpy.array
|
|||||||
new_itemsize = np.min_scalar_type(val).itemsize
|
new_itemsize = np.min_scalar_type(val).itemsize
|
||||||
if mx < new_itemsize:
|
if mx < new_itemsize:
|
||||||
mx = new_itemsize
|
mx = new_itemsize
|
||||||
|
if orig_dtype == 'int':
|
||||||
|
mx = max(mx, 4)
|
||||||
new_dtype = orig_dtype + str(mx * 8)
|
new_dtype = orig_dtype + str(mx * 8)
|
||||||
return ser.astype(new_dtype)
|
return ser.astype(new_dtype)
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import pytz
|
||||||
|
from datetime import datetime
|
||||||
|
from catalyst.api import symbol
|
||||||
|
from catalyst.utils.run_algo import run_algorithm
|
||||||
|
|
||||||
|
coin = 'btc'
|
||||||
|
base_currency = 'usd'
|
||||||
|
n_candles = 5
|
||||||
|
|
||||||
|
|
||||||
|
def initialize(context):
|
||||||
|
context.symbol = symbol('%s_%s' % (coin, base_currency))
|
||||||
|
|
||||||
|
|
||||||
|
def handle_data_polo_partial_candles(context, data):
|
||||||
|
history = data.history(symbol('btc_usdt'), ['volume'],
|
||||||
|
bar_count=10,
|
||||||
|
frequency='4H')
|
||||||
|
print('\nnow: %s\n%s' % (data.current_dt, history))
|
||||||
|
if not hasattr(context, 'i'):
|
||||||
|
context.i = 0
|
||||||
|
context.i += 1
|
||||||
|
if context.i > 5:
|
||||||
|
raise Exception('stop')
|
||||||
|
|
||||||
|
|
||||||
|
live = False
|
||||||
|
|
||||||
|
if live:
|
||||||
|
run_algorithm(initialize=lambda ctx: True,
|
||||||
|
handle_data=handle_data_polo_partial_candles,
|
||||||
|
exchange_name='poloniex',
|
||||||
|
base_currency='usdt',
|
||||||
|
algo_namespace='ns',
|
||||||
|
live=True,
|
||||||
|
data_frequency='minute',
|
||||||
|
capital_base=3000)
|
||||||
|
else:
|
||||||
|
run_algorithm(initialize=lambda ctx: True,
|
||||||
|
handle_data=handle_data_polo_partial_candles,
|
||||||
|
exchange_name='poloniex',
|
||||||
|
base_currency='usdt',
|
||||||
|
algo_namespace='ns',
|
||||||
|
live=False,
|
||||||
|
data_frequency='minute',
|
||||||
|
capital_base=3000,
|
||||||
|
start=datetime(2018, 2, 2, 0, 0, 0, 0, pytz.utc),
|
||||||
|
end=datetime(2018, 2, 20, 0, 0, 0, 0, pytz.utc)
|
||||||
|
)
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import pytz
|
||||||
|
from datetime import datetime
|
||||||
|
from catalyst.api import symbol
|
||||||
|
from catalyst.utils.run_algo import run_algorithm
|
||||||
|
|
||||||
|
coin = 'btc'
|
||||||
|
base_currency = 'usd'
|
||||||
|
|
||||||
|
|
||||||
|
def initialize(context):
|
||||||
|
context.symbol = symbol('%s_%s' % (coin, base_currency))
|
||||||
|
|
||||||
|
|
||||||
|
def handle_data_polo_partial_candles(context, data):
|
||||||
|
history = data.history(symbol('btc_usdt'), ['volume'],
|
||||||
|
bar_count=10,
|
||||||
|
frequency='1D')
|
||||||
|
print('\nnow: %s\n%s' % (data.current_dt, history))
|
||||||
|
if not hasattr(context, 'i'):
|
||||||
|
context.i = 0
|
||||||
|
context.i += 1
|
||||||
|
if context.i > 5:
|
||||||
|
raise Exception('stop')
|
||||||
|
|
||||||
|
|
||||||
|
run_algorithm(initialize=lambda ctx: True,
|
||||||
|
handle_data=handle_data_polo_partial_candles,
|
||||||
|
exchange_name='poloniex',
|
||||||
|
base_currency='usdt',
|
||||||
|
algo_namespace='ns',
|
||||||
|
live=False,
|
||||||
|
data_frequency='minute',
|
||||||
|
capital_base=3000,
|
||||||
|
start=datetime(2018, 2, 2, 0, 0, 0, 0, pytz.utc),
|
||||||
|
end=datetime(2018, 2, 20, 0, 0, 0, 0, pytz.utc))
|
||||||
+11
-1
@@ -143,7 +143,7 @@ with the following steps:
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
conda create --name catalyst python=2.7 scipy zlib
|
conda create --name catalyst python=3.6 scipy zlib
|
||||||
|
|
||||||
3. Activate the environment:
|
3. Activate the environment:
|
||||||
|
|
||||||
@@ -314,6 +314,16 @@ Troubleshooting ``pip`` Install
|
|||||||
|
|
||||||
$ sudo apt-get install python-dev
|
$ sudo apt-get install python-dev
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
**Issue**:
|
||||||
|
Missing TA_Lib
|
||||||
|
|
||||||
|
**Solution**:
|
||||||
|
Follow `these instructions
|
||||||
|
<https://mrjbq7.github.io/ta-lib/install.html>`_ to install the TA_Lib Python wrapper
|
||||||
|
(and if needed, its underlying C library as well).
|
||||||
|
|
||||||
.. _pipenv:
|
.. _pipenv:
|
||||||
|
|
||||||
Installing with ``pipenv``
|
Installing with ``pipenv``
|
||||||
|
|||||||
@@ -2,6 +2,52 @@
|
|||||||
Release Notes
|
Release Notes
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
Version 0.5.5
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
**Release Date**: 2018-03-19
|
||||||
|
|
||||||
|
Bug Fixes
|
||||||
|
~~~~~~~~~
|
||||||
|
- Fixed an issue with the data history in daily frequency :issue:`274`
|
||||||
|
- Fix hourly frequency issues :issue:`227` and :issue:`114`
|
||||||
|
|
||||||
|
Version 0.5.4
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
**Release Date**: 2018-03-14
|
||||||
|
|
||||||
|
Build
|
||||||
|
~~~~~
|
||||||
|
- Switched Data Marketplace from Ropstein testnet to Rinkeby testnet after
|
||||||
|
incorporating changes resulting from the marketplace contract audit
|
||||||
|
- Several usability improvements of the Data Marketplace that make the
|
||||||
|
`--dataset` parameter optional. If it is not included in the command line,
|
||||||
|
will list available datasets, and let you choose interactively.
|
||||||
|
|
||||||
|
Bug Fixes
|
||||||
|
~~~~~~~~~
|
||||||
|
- Fix Binance requirement of symbol to be included in the cancelled order
|
||||||
|
:issue:`204`
|
||||||
|
- Fix `notenoughcasherror` when an open order is filled minutes later
|
||||||
|
:issue:`237`
|
||||||
|
- Properly handle of empty candles received from exchanges :issue:`236`
|
||||||
|
- Added a function to reduce open orders amount from calculated target/amount
|
||||||
|
for target orders :issue:`243`
|
||||||
|
- Fix missing file in live trading mode on date change :issue:`252`,
|
||||||
|
:issue:`253`
|
||||||
|
- Upgraded Data Marketplace to Web3==4.0.0b11, which was breaking some
|
||||||
|
functionality from prior version 4.0.0b7 :issue:`257`
|
||||||
|
- Always request more data to avoid empty bars and always give the exact bar
|
||||||
|
number :issue:`260`
|
||||||
|
|
||||||
|
Documentation
|
||||||
|
~~~~~~~~~~~~~
|
||||||
|
- PyCharm documentation :issue:`195`
|
||||||
|
- Added TA-Lib troubleshooting instructions
|
||||||
|
- Added instructions on how to create a Conda environment for Python 3.6, and
|
||||||
|
updated Visual C++ instructions for Windows and Python 3
|
||||||
|
- Linking example algorithms in the documentation to their sources
|
||||||
|
|
||||||
|
|
||||||
Version 0.5.3
|
Version 0.5.3
|
||||||
^^^^^^^^^^^^^
|
^^^^^^^^^^^^^
|
||||||
**Release Date**: 2018-02-09
|
**Release Date**: 2018-02-09
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ channels:
|
|||||||
dependencies:
|
dependencies:
|
||||||
- certifi=2016.2.28=py27_0
|
- certifi=2016.2.28=py27_0
|
||||||
- mkl=2017.0.3
|
- mkl=2017.0.3
|
||||||
- matplotlib=2.1.2=py36_0
|
|
||||||
- numpy=1.13.1=py27_0
|
- numpy=1.13.1=py27_0
|
||||||
- openssl=1.0.2l
|
- openssl=1.0.2l
|
||||||
- pip=9.0.1=py27_1
|
- pip=9.0.1=py27_1
|
||||||
@@ -40,7 +39,7 @@ dependencies:
|
|||||||
- lru-dict==1.1.6
|
- lru-dict==1.1.6
|
||||||
- mako==1.0.7
|
- mako==1.0.7
|
||||||
- markupsafe==1.0
|
- markupsafe==1.0
|
||||||
- matplotlib==2.1.0
|
- matplotlib==2.1.2
|
||||||
- multipledispatch==0.4.9
|
- multipledispatch==0.4.9
|
||||||
- networkx==2.0
|
- networkx==2.0
|
||||||
- numexpr==2.6.4
|
- numexpr==2.6.4
|
||||||
|
|||||||
Reference in New Issue
Block a user