mirror of
https://github.com/wassname/catalyst.git
synced 2026-08-20 12:10:30 +08:00
Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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))
|
||||||
|
|||||||
@@ -13,10 +13,12 @@ from catalyst.exchange.exchange_errors import MismatchingBaseCurrencies, \
|
|||||||
PricingDataNotLoadedError, \
|
PricingDataNotLoadedError, \
|
||||||
NoDataAvailableOnExchange, NoValueForField, \
|
NoDataAvailableOnExchange, NoValueForField, \
|
||||||
NoCandlesReceivedFromExchange, \
|
NoCandlesReceivedFromExchange, \
|
||||||
|
InvalidHistoryFrequencyAlias, \
|
||||||
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
|
||||||
@@ -507,11 +509,20 @@ class Exchange:
|
|||||||
frequency, data_frequency, supported_freqs=['T', 'D', 'H']
|
frequency, data_frequency, supported_freqs=['T', 'D', 'H']
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if unit == 'H':
|
||||||
|
raise InvalidHistoryFrequencyAlias(
|
||||||
|
freq=frequency)
|
||||||
|
|
||||||
# we want to avoid receiving empty candles
|
# we want to avoid receiving empty candles
|
||||||
# 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 +540,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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
@@ -326,3 +327,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:
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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,43 @@
|
|||||||
Release Notes
|
Release Notes
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
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
|
||||||
|
|||||||
Reference in New Issue
Block a user