def send_notification_email(self, gdax, bitcoin_de, profit_pct): try: email = EmailBuilder.build_notification_email( gdax, bitcoin_de, profit_pct) response = self.email_client.send_email( Destination={ 'ToAddresses': [ self._recipient, ], }, Message={ 'Body': { 'Text': { 'Charset': self._charset, 'Data': email['text'] }, }, 'Subject': { 'Charset': self._charset, 'Data': email['subject'] }, }, Source=self._sender, ) Log.info( self.ME, 'Just sent a notification email. Profit: {} %.'.format( profit_pct)) except Exception as e: Log.error(self.ME, 'Unable to send notification email: {}'.format(e)) return False return True
def get_gdax_ask(self, pair): try: gdax_order_book = self.GDAX_CLIENT.get_product_order_book(pair, level=1) return self.parse_gdax_order_book(gdax_order_book, pair) except Exception as e: Log.warn(self.ME, 'Unable to fetch new ask from gdax.com: {}'.format(e)) return None
def __init__(self): self.fidor_password = os.environ['FIDOR_PASSWORD'] self.fidor_email = os.environ['FIDOR_EMAIL'] options = webdriver.ChromeOptions() options.add_argument('headless') options.add_argument('no-sandbox') try: self.client = webdriver.Chrome(chrome_options=options) Log.debug(self.ME, 'Launched new chromedriver instance.') except Exception as e: Log.fatal(self.ME, 'Unable to create chrome client: {}'.format(e))
def handle(self, *args, **options): last_gdax_ask_btc = None last_gdax_ask_eth = None last_bitcoin_de_ask_btc = None while True: bitcoin_ask_btc = self.get_bitcoin_ask('BTC') if bitcoin_ask_btc is not None: bitcoin_ask_btc.save() last_bitcoin_de_ask_btc = bitcoin_ask_btc Log.info(self.ME, 'Fetched new ask: {}'.format(last_bitcoin_de_ask_btc)) bitcoin_ask_eth = self.get_bitcoin_ask('ETH') if bitcoin_ask_eth is not None: bitcoin_ask_eth.save() last_bitcoin_de_ask_eth = bitcoin_ask_eth Log.info(self.ME, 'Fetched new ask: {}'.format(last_bitcoin_de_ask_eth)) gdax_ask_btc = self.get_gdax_ask('BTC-EUR') if gdax_ask_btc is not None: gdax_ask_btc.save() last_gdax_ask_btc = gdax_ask_btc Log.info(self.ME, 'Fetched new ask: {}'.format(last_gdax_ask_btc)) gdax_ask_eth = self.get_gdax_ask('ETH-EUR') if gdax_ask_eth is not None: gdax_ask_eth.save() last_gdax_ask_eth = gdax_ask_eth Log.info(self.ME, 'Fetched new ask: {}'.format(last_gdax_ask_eth)) pct_profit = self.calc_profit_pct_btc(last_gdax_ask_btc, last_bitcoin_de_ask_btc) allowed_to_send_email = self.last_notification_email is None or ( datetime.now() - self.last_notification_email ).seconds // 60 > self.NOTIFICATION_EMAIL_PAUSE_MIN if pct_profit > self.NOTIFICATION_THRESHOLD_PCT and allowed_to_send_email: success = self.send_notification_email( last_gdax_ask_btc, last_bitcoin_de_ask_btc, pct_profit) if success: self.last_notification_email = datetime.now() # TODO: Fix. Should really fire every minute and not sleep for 60s. self.heartbeat() time.sleep(60) return 0
def update_transactions(self): """ Keeps turn overs up-to-date """ TRANSACTIONS_URL = 'https://banking.fidor.de/smart-account/transactions' self.client.get(TRANSACTIONS_URL) transactions = self.client.find_elements_by_css_selector( '#booked-transactions tbody tr') new_transactions = [] for t in transactions: cols = t.find_elements_by_tag_name('td') try: date = datetime.strptime(cols[0].text, '%d.%m.%Y') desc = cols[1].text amount = float(cols[2].text.strip("€").replace('.', '').replace( ',', '.')) balance = float(cols[3].text.strip('€').replace('.', '').replace( ',', '.')) unique = sha256('{}-{}-{}-{}'.format( date, desc, amount, balance).encode('utf-8')).hexdigest() result = BankTransaction.objects.filter(unique=unique) if result: break # Look for open transactions that can be closed open_transaction = BankTransaction.objects.filter( amount=amount, finished=False).first() if open_transaction: open_transaction.arrived_at = date open_transaction.desc = desc open_transaction.unique = unique open_transaction.finished = True open_transaction.new_balance = balance open_transaction.save() Log.info( self.ME, 'A pending SEPA transaction of {} € just arrived. New balance: {} €.' .format(open_transaction.amount, open_transaction.new_balance)) else: new_transactions.append( BankTransaction(finished=True, arrived_on=date, desc=desc, amount=amount, new_balance=balance, unique=unique)) except Exception as e: Log.warn(self.ME, 'Unable to store new SEPA transaction: {}'.format(e)) for t in reversed(new_transactions): Log.info( self.ME, 'An unexpected SEPA transaction of {} € just arrived. New balance: {} €.' .format(t.amount, t.new_balance)) t.save()
def get_bitcoin_ask(self, coin): try: if coin == 'BTC': self.bitcoin_conn.request('GET', self.BTC_OFFER_RESOURCE, None, self.CLIENT_HEADER) resp = self.bitcoin_conn.getresponse() if resp.status == 200: asks = html.fragments_fromstring(resp.read()) for a in asks: ask = self.parse_ask_btc(a) if (self.valid(ask)): return ask else: Log.warn( self.ME, 'Unable to fetch new ask from bitcoin.de: [status={}, reason={}]' .format(resp.status, resp.reason)) elif coin == 'ETH': self.bitcoin_conn.request('GET', self.ETH_OFFER_RESOURCE, None, self.CLIENT_HEADER_ETH) resp = self.bitcoin_conn.getresponse() if resp.status == 200: asks = html.fragments_fromstring(resp.read()) for a in asks: ask = self.parse_ask_eth(a) if (self.valid(ask)): return ask else: Log.warn( self.ME, 'Unable to fetch new ask from bitcoin.de: [status={}, reason={}]' .format(resp.status, resp.reason)) except Exception as e: Log.warn(self.ME, 'Unable to fetch new ask from bitcoin.de: {}'.format(e)) self.create_btc_conn() return None