forked from freqtrade/freqtrade
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
gcarq
committed
May 12, 2017
0 parents
commit e5d693e
Showing
11 changed files
with
726 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
config.json | ||
preprocessor.py | ||
*.sqlite |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
{ | ||
"stake_amount": 0.05, | ||
"dry_run": false, | ||
"trade_thresholds": { | ||
"2880": 0.005, | ||
"1440": 0.01, | ||
"720": 0.03, | ||
"360": 0.05, | ||
"0": 0.10 | ||
}, | ||
"poloniex": { | ||
"enabled": false, | ||
"key": "key", | ||
"secret": "secret", | ||
"pair_whitelist": [] | ||
}, | ||
"bittrex": { | ||
"enabled": true, | ||
"key": "key", | ||
"secret": "secret", | ||
"pair_whitelist": [ | ||
"BTC_MLN", | ||
"BTC_TRST", | ||
"BTC_TIME", | ||
"BTC_NXS", | ||
"BTC_GBYTE", | ||
"BTC_SNGLS" | ||
] | ||
}, | ||
"telegram": { | ||
"enabled": true, | ||
"token": "token", | ||
"chat_id": "chat_id" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
import enum | ||
import threading | ||
|
||
from bittrex.bittrex import Bittrex | ||
from poloniex import Poloniex | ||
|
||
|
||
_lock = threading.Condition() | ||
_exchange_api = None | ||
|
||
|
||
def get_exchange_api(conf): | ||
""" | ||
Returns the current exchange api or instantiates a new one | ||
:return: exchange.ApiWrapper | ||
""" | ||
global _exchange_api | ||
_lock.acquire() | ||
if not _exchange_api: | ||
_exchange_api = ApiWrapper(conf) | ||
_lock.release() | ||
return _exchange_api | ||
|
||
|
||
class Exchange(enum.Enum): | ||
POLONIEX = 0 | ||
BITTREX = 1 | ||
|
||
|
||
class ApiWrapper(object): | ||
""" | ||
Wrapper for exchanges. | ||
Currently implemented: | ||
* Bittrex | ||
* Poloniex (partly) | ||
""" | ||
def __init__(self, config): | ||
""" | ||
Initializes the ApiWrapper with the given config, it does not validate those values. | ||
:param config: dict | ||
""" | ||
self.dry_run = config['dry_run'] | ||
|
||
use_poloniex = config.get('poloniex', {}).get('enabled', False) | ||
use_bittrex = config.get('bittrex', {}).get('enabled', False) | ||
|
||
if use_poloniex: | ||
self.exchange = Exchange.POLONIEX | ||
self.api = Poloniex( | ||
key=config['poloniex']['key'], | ||
secret=config['poloniex']['secret'] | ||
) | ||
elif use_bittrex: | ||
self.exchange = Exchange.BITTREX | ||
self.api = Bittrex( | ||
api_key=config['bittrex']['key'], | ||
api_secret=config['bittrex']['secret'] | ||
) | ||
else: | ||
self.api = None | ||
|
||
def buy(self, pair, rate, amount): | ||
""" | ||
Places a limit buy order. | ||
:param pair: Pair as str, format: BTC_ETH | ||
:param rate: Rate limit for order | ||
:param amount: The amount to purchase | ||
:return: None | ||
""" | ||
if self.dry_run: | ||
pass | ||
elif self.exchange == Exchange.POLONIEX: | ||
self.api.buy(pair, rate, amount) | ||
elif self.exchange == Exchange.BITTREX: | ||
data = self.api.buy_limit(pair.replace('_', '-'), amount, rate) | ||
if not data['success']: | ||
raise RuntimeError('BITTREX: {}'.format(data['message'])) | ||
|
||
def sell(self, pair, rate, amount): | ||
""" | ||
Places a limit sell order. | ||
:param pair: Pair as str, format: BTC_ETH | ||
:param rate: Rate limit for order | ||
:param amount: The amount to sell | ||
:return: None | ||
""" | ||
if self.dry_run: | ||
pass | ||
elif self.exchange == Exchange.POLONIEX: | ||
self.api.sell(pair, rate, amount) | ||
elif self.exchange == Exchange.BITTREX: | ||
data = self.api.sell_limit(pair.replace('_', '-'), amount, rate) | ||
if not data['success']: | ||
raise RuntimeError('BITTREX: {}'.format(data['message'])) | ||
|
||
def get_balance(self, currency): | ||
""" | ||
Get account balance. | ||
:param currency: currency as str, format: BTC | ||
:return: float | ||
""" | ||
if self.exchange == Exchange.POLONIEX: | ||
data = self.api.returnBalances() | ||
return float(data[currency]) | ||
elif self.exchange == Exchange.BITTREX: | ||
data = self.api.get_balance(currency) | ||
if not data['success']: | ||
raise RuntimeError('BITTREX: {}'.format(data['message'])) | ||
return float(data['result']['Balance'] or 0.0) | ||
|
||
def get_ticker(self, pair): | ||
""" | ||
Get Ticker for given pair. | ||
:param pair: Pair as str, format: BTC_ETC | ||
:return: dict | ||
""" | ||
if self.exchange == Exchange.POLONIEX: | ||
data = self.api.returnTicker() | ||
return { | ||
'bid': float(data[pair]['highestBid']), | ||
'ask': float(data[pair]['lowestAsk']), | ||
'last': float(data[pair]['last']) | ||
} | ||
elif self.exchange == Exchange.BITTREX: | ||
data = self.api.get_ticker(pair.replace('_', '-')) | ||
if not data['success']: | ||
raise RuntimeError('BITTREX: {}'.format(data['message'])) | ||
return { | ||
'bid': float(data['result']['Bid']), | ||
'ask': float(data['result']['Ask']), | ||
'last': float(data['result']['Last']), | ||
} | ||
|
||
def get_open_orders(self, pair): | ||
""" | ||
Get all open orders for given pair. | ||
:param pair: Pair as str, format: BTC_ETC | ||
:return: list of dicts | ||
""" | ||
if self.exchange == Exchange.POLONIEX: | ||
raise NotImplemented('Not implemented') | ||
elif self.exchange == Exchange.BITTREX: | ||
data = self.api.get_open_orders(pair.replace('_', '-')) | ||
if not data['success']: | ||
raise RuntimeError('BITTREX: {}'.format(data['message'])) | ||
return [{ | ||
'type': entry['OrderType'], | ||
'opened': entry['Opened'], | ||
'rate': entry['PricePerUnit'], | ||
'amount': entry['Quantity'], | ||
'remaining': entry['QuantityRemaining'], | ||
} for entry in data['result']] |
Oops, something went wrong.