|
@ -2,6 +2,8 @@ from datetime import datetime |
|
|
import inspect |
|
|
import inspect |
|
|
import requests |
|
|
import requests |
|
|
import sys |
|
|
import sys |
|
|
|
|
|
import os |
|
|
|
|
|
import json |
|
|
from threading import Thread |
|
|
from threading import Thread |
|
|
import time |
|
|
import time |
|
|
import csv |
|
|
import csv |
|
@ -59,19 +61,34 @@ class ExchangeBase(PrintError): |
|
|
t.setDaemon(True) |
|
|
t.setDaemon(True) |
|
|
t.start() |
|
|
t.start() |
|
|
|
|
|
|
|
|
def get_historical_rates_safe(self, ccy): |
|
|
def get_historical_rates_safe(self, ccy, cache_dir): |
|
|
try: |
|
|
filename = os.path.join(cache_dir, self.name() + '_'+ ccy) |
|
|
self.print_error("requesting fx history for", ccy) |
|
|
if os.path.exists(filename) and (time.time() - os.stat(filename).st_mtime) < 24*3600: |
|
|
self.history[ccy] = self.historical_rates(ccy) |
|
|
try: |
|
|
self.print_error("received fx history for", ccy) |
|
|
with open(filename, 'r') as f: |
|
|
self.on_history() |
|
|
h = json.loads(f.read()) |
|
|
except BaseException as e: |
|
|
except: |
|
|
self.print_error("failed fx history:", e) |
|
|
h = None |
|
|
|
|
|
else: |
|
|
def get_historical_rates(self, ccy): |
|
|
h = None |
|
|
|
|
|
if h is None: |
|
|
|
|
|
try: |
|
|
|
|
|
self.print_error("requesting fx history for", ccy) |
|
|
|
|
|
h = self.request_history(ccy) |
|
|
|
|
|
self.print_error("received fx history for", ccy) |
|
|
|
|
|
self.on_history() |
|
|
|
|
|
except BaseException as e: |
|
|
|
|
|
self.print_error("failed fx history:", e) |
|
|
|
|
|
return |
|
|
|
|
|
with open(filename, 'w') as f: |
|
|
|
|
|
f.write(json.dumps(h)) |
|
|
|
|
|
self.history[ccy] = h |
|
|
|
|
|
self.on_history() |
|
|
|
|
|
|
|
|
|
|
|
def get_historical_rates(self, ccy, cache_dir): |
|
|
result = self.history.get(ccy) |
|
|
result = self.history.get(ccy) |
|
|
if not result and ccy in self.history_ccys(): |
|
|
if not result and ccy in self.history_ccys(): |
|
|
t = Thread(target=self.get_historical_rates_safe, args=(ccy,)) |
|
|
t = Thread(target=self.get_historical_rates_safe, args=(ccy, cache_dir)) |
|
|
t.setDaemon(True) |
|
|
t.setDaemon(True) |
|
|
t.start() |
|
|
t.start() |
|
|
return result |
|
|
return result |
|
@ -99,7 +116,7 @@ class BitcoinAverage(ExchangeBase): |
|
|
'MXN', 'NOK', 'NZD', 'PLN', 'RON', 'RUB', 'SEK', 'SGD', 'USD', |
|
|
'MXN', 'NOK', 'NZD', 'PLN', 'RON', 'RUB', 'SEK', 'SGD', 'USD', |
|
|
'ZAR'] |
|
|
'ZAR'] |
|
|
|
|
|
|
|
|
def historical_rates(self, ccy): |
|
|
def request_history(self, ccy): |
|
|
history = self.get_csv('apiv2.bitcoinaverage.com', |
|
|
history = self.get_csv('apiv2.bitcoinaverage.com', |
|
|
"/indices/global/history/BTC%s?period=alltime&format=csv" % ccy) |
|
|
"/indices/global/history/BTC%s?period=alltime&format=csv" % ccy) |
|
|
return dict([(h['DateTime'][:10], h['Average']) |
|
|
return dict([(h['DateTime'][:10], h['Average']) |
|
@ -127,7 +144,7 @@ class BitcoinVenezuela(ExchangeBase): |
|
|
def history_ccys(self): |
|
|
def history_ccys(self): |
|
|
return ['ARS', 'EUR', 'USD', 'VEF'] |
|
|
return ['ARS', 'EUR', 'USD', 'VEF'] |
|
|
|
|
|
|
|
|
def historical_rates(self, ccy): |
|
|
def request_history(self, ccy): |
|
|
return self.get_json('api.bitcoinvenezuela.com', |
|
|
return self.get_json('api.bitcoinvenezuela.com', |
|
|
"/historical/index.php?coin=BTC")[ccy +'_BTC'] |
|
|
"/historical/index.php?coin=BTC")[ccy +'_BTC'] |
|
|
|
|
|
|
|
@ -216,7 +233,7 @@ class CoinDesk(ExchangeBase): |
|
|
def history_ccys(self): |
|
|
def history_ccys(self): |
|
|
return self.history_starts().keys() |
|
|
return self.history_starts().keys() |
|
|
|
|
|
|
|
|
def historical_rates(self, ccy): |
|
|
def request_history(self, ccy): |
|
|
start = self.history_starts()[ccy] |
|
|
start = self.history_starts()[ccy] |
|
|
end = datetime.today().strftime('%Y-%m-%d') |
|
|
end = datetime.today().strftime('%Y-%m-%d') |
|
|
# Note ?currency and ?index don't work as documented. Sigh. |
|
|
# Note ?currency and ?index don't work as documented. Sigh. |
|
@ -314,7 +331,7 @@ class Winkdex(ExchangeBase): |
|
|
def history_ccys(self): |
|
|
def history_ccys(self): |
|
|
return ['USD'] |
|
|
return ['USD'] |
|
|
|
|
|
|
|
|
def historical_rates(self, ccy): |
|
|
def request_history(self, ccy): |
|
|
json = self.get_json('winkdex.com', |
|
|
json = self.get_json('winkdex.com', |
|
|
"/api/v0/series?start_time=1342915200") |
|
|
"/api/v0/series?start_time=1342915200") |
|
|
history = json['series'][0]['results'] |
|
|
history = json['series'][0]['results'] |
|
@ -381,6 +398,9 @@ class FxThread(ThreadJob): |
|
|
self.ccy_combo = None |
|
|
self.ccy_combo = None |
|
|
self.hist_checkbox = None |
|
|
self.hist_checkbox = None |
|
|
self.set_exchange(self.config_exchange()) |
|
|
self.set_exchange(self.config_exchange()) |
|
|
|
|
|
self.cache_dir = os.path.join(config.path, 'cache') |
|
|
|
|
|
if not os.path.exists(self.cache_dir): |
|
|
|
|
|
os.mkdir(self.cache_dir) |
|
|
|
|
|
|
|
|
def get_currencies(self, h): |
|
|
def get_currencies(self, h): |
|
|
d = get_exchanges_by_ccy(h) |
|
|
d = get_exchanges_by_ccy(h) |
|
@ -403,7 +423,7 @@ class FxThread(ThreadJob): |
|
|
# This runs from the plugins thread which catches exceptions |
|
|
# This runs from the plugins thread which catches exceptions |
|
|
if self.is_enabled(): |
|
|
if self.is_enabled(): |
|
|
if self.timeout ==0 and self.show_history(): |
|
|
if self.timeout ==0 and self.show_history(): |
|
|
self.exchange.get_historical_rates(self.ccy) |
|
|
self.exchange.get_historical_rates(self.ccy, self.cache_dir) |
|
|
if self.timeout <= time.time(): |
|
|
if self.timeout <= time.time(): |
|
|
self.timeout = time.time() + 150 |
|
|
self.timeout = time.time() + 150 |
|
|
self.exchange.update(self.ccy) |
|
|
self.exchange.update(self.ccy) |
|
|