def test_get_ticker_price_no_market(bitvavo_credentials): market = "BTC-EUR" b_client = BitvavoClient( api_key=bitvavo_credentials['bitvavo_access_key'], api_secret=bitvavo_credentials['bitvavo-access-signature'], _response_ticker_price={ "market": market, "price": "5003.2" }) assert b_client.get_ticker_price() is None
def update_alerts(self): for idx, alert in enumerate(self.alerts): updated = self.alerts[idx].update_by_client() if updated is False: continue if self.alerts[idx].status != self.alerts[idx].STATUS_HIT: continue if self.alerts[idx].is_ticker_price_diverted(): Messages.send_email( json.dumps( { "alert_price": self.alerts[idx].price, "backup_price": self.alerts[idx].backup_price }, indent=4, sort_keys=True, default=str ), 'Ticker price diversion' ) continue if Alert.ACTION_SELL_ASSET in self.alerts[idx].actions: trade = Trade( _client=BitvavoClient(market=self.alerts[idx].market), _alert=self.alerts[idx] ) trade.sell() if Alert.ACTION_SEND_EMAIL in self.alerts[idx].actions: Messages.send_email(json.dumps(self.alerts[idx].attributes(), indent=4, sort_keys=True, default=str))
def test_trailing_price_hit(): actions = [] market = 'ETH-EUR' init_price = Decimal('1000') price = Decimal('950') ticker_price = Decimal('800') trailing_percentage = Decimal('0.9') trailing_price = init_price * trailing_percentage alert = Alert(actions=actions, dt=datetime.datetime.now(), init_price=init_price, market=market, price=price, status=Alert.STATUS_ACTIVE, trailing_percentage=trailing_percentage, trailing_price=trailing_price, _client=BitvavoClient(market=market, _response_ticker_price={ "market": market, "price": ticker_price })) alert.update_by_client() assert alert.actions == actions assert alert.init_price == init_price assert alert.market == market assert alert.price == ticker_price assert alert.status == Alert.STATUS_HIT assert alert.trailing_percentage == trailing_percentage assert alert.trailing_price == trailing_price
def test_populate_new_alert_init_price_not_set(): actions = [] market = 'ETH-EUR' init_price = None price = Decimal('1000') ticker_price = Decimal('1511.7') trailing_percentage = Decimal('0.9') trailing_price = ticker_price * trailing_percentage alert = Alert(actions=actions, dt=datetime.datetime.now(), init_price=init_price, market=market, price=price, status=Alert.STATUS_NOT_INIT, trailing_percentage=trailing_percentage, trailing_price=trailing_price, _client=BitvavoClient(market=market, _response_ticker_price={ "market": market, "price": ticker_price })) assert alert.update_by_client() is False assert alert.actions == actions assert alert.init_price is None assert alert.market == market assert alert.price == price assert alert.status == Alert.STATUS_NOT_INIT assert alert.trailing_percentage == trailing_percentage assert alert.trailing_price == trailing_percentage * ticker_price
def test_create_alert_by_params(tmp_path): d = tmp_path / "sub" d.mkdir() file_name = 'new_alert.json' market = 'ADA-EUR' alert_trailing_percentage = Decimal('0.9') market_selection_type = '2' actions_selection = '1' init_price_type = '2' price = Decimal('1.004') ca = CreateAlert(alert_trailing_percentage=alert_trailing_percentage, market_selection_type=market_selection_type, market=market, actions_selection=actions_selection, init_price_type=init_price_type, file_name=file_name, alerts_file_path=str(d) + '/', _client=BitvavoClient(market=market, _response_ticker_price={ "market": market, "price": price })) ca.add_by_console() with open(d / file_name, 'r') as fp: alerts = json.load(fp, parse_float=get_decimal, parse_int=get_decimal) assert alerts['market'] == market assert alerts['price'] == price assert alerts['trailing_percentage'] == alert_trailing_percentage
def get_alert(**kwargs): status = kwargs.get("status") client_response_ticker_price_scenario = kwargs.get( "client_response_ticker_price_scenario") client_response_ticker_price = None market = kwargs.get('market', 'ETH-EUR') fake = Faker() trailing_price = fake.pydecimal(min_value=100) trailing_percentage = Decimal('0.' + str(fake.pyint(min_value=70, max_value=97))) init_price = trailing_price / trailing_percentage + fake.pydecimal( min_value=100, max_value=200) if status == Alert.STATUS_ACTIVE: price = trailing_price / trailing_percentage + fake.pydecimal( min_value=100, max_value=200) elif status == Alert.STATUS_HIT: price = trailing_price / trailing_percentage else: return None if client_response_ticker_price_scenario is not None: if client_response_ticker_price_scenario == 'hit': client_response_ticker_price = trailing_price - fake.pydecimal( min_value=30, max_value=80) elif client_response_ticker_price_scenario == 'increased': client_response_ticker_price = price + fake.pydecimal(min_value=30, max_value=80) elif client_response_ticker_price_scenario == 'decreased': client_response_ticker_price = fake.pydecimal( min_value=int(trailing_price + 1), max_value=int(price - 1)) dt = fake.date_time() + datetime.timedelta(microseconds=1) return Alert(amount=None, actions=[], dt=dt, init_dt=dt, init_price=init_price, market=market, price=price, status=status, trailing_percentage=trailing_percentage, trailing_price=trailing_price, _client=BitvavoClient(market=market, _response_ticker_price={ "market": market, "price": client_response_ticker_price }))
def load_alerts(self): alerts = list() try: with open(self.alerts_file_path + self.alerts_file_name, 'r') as fp: alerts = json.load(fp, parse_float=self.get_decimal, parse_int=self.get_decimal) except FileNotFoundError: logging.info('No alert file.') Path(self.alerts_file_path + self.alerts_file_name).touch() logging.info('Created alert file.') return except simplejson.errors.JSONDecodeError as e: logging.warning(e) # load new alert from dedicated file if self.new_alert_file_name is not None: try: with open(self.alerts_file_path + self.new_alert_file_name, 'r') as fp: alerts.append(json.load(fp, parse_float=self.get_decimal, parse_int=self.get_decimal)) os.remove(self.alerts_file_path + self.new_alert_file_name) except FileNotFoundError: logging.debug('No new alert file.') except simplejson.errors.JSONDecodeError as e: logging.warning(e) if not alerts: logging.warning("No alerts set.") for idx, alert in enumerate(alerts): alert = Alert( actions=alert['actions'], amount=alert['amount'], dt=datetime.datetime.strptime(alert['dt'], "%Y-%m-%d %H:%M:%S.%f"), init_dt=datetime.datetime.strptime(alert['init_dt'], "%Y-%m-%d %H:%M:%S.%f"), init_price=alert['init_price'], market=alert['market'], price=alert['price'], status=alert['status'], trailing_percentage=alert['trailing_percentage'], trailing_price=alert['trailing_price'], _client=BitvavoClient( market=alert['market'] ) ) self.alerts.append(alert) logging.debug('ALERT:load_alerts:loaded_alerts:' + str(self.alerts))
class CreateAlert(object): _client: BitvavoClient = None file_name: str = os.environ.get('ALERTS_FILE_NAME') alerts_file_path: str = None alert = None actions: list = None alert_init_price = None alert_trailing_percentage = None market = None actions_selection = None init_price_type = None market_selection_type = None def __init__(self, **kwargs): self.actions = [] self.alerts_file_path = os.environ.get('ALERTS_FILE_PATH') if len(sys.argv) > 1 and 'test_create_alert_logic' not in sys.argv[1]: if len(sys.argv) > 1: self.alert_trailing_percentage = Decimal(sys.argv[1]) if len(sys.argv) > 2: self.market_selection_type = sys.argv[2] if len(sys.argv) > 3: self.market = sys.argv[3] if len(sys.argv) > 4: self.actions_selection = sys.argv[4] if len(sys.argv) > 5: self.init_price_type = Decimal(sys.argv[5]) if len(sys.argv) > 6: self.alert_init_price = Decimal(sys.argv[6]) self.alerts_file_path = os.environ.get('ALERTS_FILE_PATH') for k, v in kwargs.items(): self.__setattr__(k, v) def save_alert(self): with open(self.alerts_file_path + self.file_name, 'w') as fp: json.dump(self.alert.attributes(), fp, indent=4, sort_keys=True, default=str) def add_by_console(self): if os.path.isfile(self.file_name): print( "Pending new alert, try again please (Updating process probably didn't yet pick up new alert)." ) exit(1) print('Input new alert data:') print('---------------------') if self.market is None: self.choose_market() print('Add new init price:') print(' [1] Use manual value') print(' [2] Set by market') if self.init_price_type is None: self.init_price_type = input() if self.init_price_type == '1' and self.alert_init_price is None: print('Type in your value for init price as string like "2345.43"') self.alert_init_price = Decimal(input()) if self.alert_trailing_percentage is None: print('Insert trail in percentage like ["0.9", "0.45"]') self.alert_trailing_percentage = Decimal(input()) if self.actions_selection is None: print('Which actions should be activated?') print('[1] Send e-mail') print('[2] Sell') print('[3] Send e-mail and sell') self.actions_selection = input() if self.actions_selection == '1': self.actions.append(Alert.ACTION_SEND_EMAIL) if self.actions_selection == '2': self.actions.append(Alert.ACTION_SELL_ASSET) elif self.actions_selection == '3': self.actions.extend( [Alert.ACTION_SEND_EMAIL, Alert.ACTION_SELL_ASSET]) if self._client is None: self._client = BitvavoClient(market=self.market) self.alert = Alert(actions=self.actions, init_price=self.alert_init_price, trailing_percentage=self.alert_trailing_percentage, market=self.market, _client=self._client) if not self.alert.init_attributes(): print('Error occurred.') self.save_alert() print('New alert created.') print(self.alert.attributes()) def choose_market(self): print('Choose market, like "ETH-EUR"') print(' [1] Type in your market string') print(' [2] List supported markets') self.market_selection_type = input() if self.market_selection_type == '1': print('Type in your market string') self.market = input() elif self.market_selection_type == '2': markets = self._client.get_markets() print('Supported markets:') print(json.dumps(markets, indent=4, sort_keys=True)) self.market = self.choose_market() else: print('Input not recognized.') exit(1) if not self.is_market_supported(self.market): print('Market string not supported.') exit(1) return self.market def is_market_supported(self, market): remote_market = self._client.get_markets(market) if \ 'market' in remote_market and \ market == remote_market['market'] and \ 'trading' == remote_market['status']: return True return False
def add_by_console(self): if os.path.isfile(self.file_name): print( "Pending new alert, try again please (Updating process probably didn't yet pick up new alert)." ) exit(1) print('Input new alert data:') print('---------------------') if self.market is None: self.choose_market() print('Add new init price:') print(' [1] Use manual value') print(' [2] Set by market') if self.init_price_type is None: self.init_price_type = input() if self.init_price_type == '1' and self.alert_init_price is None: print('Type in your value for init price as string like "2345.43"') self.alert_init_price = Decimal(input()) if self.alert_trailing_percentage is None: print('Insert trail in percentage like ["0.9", "0.45"]') self.alert_trailing_percentage = Decimal(input()) if self.actions_selection is None: print('Which actions should be activated?') print('[1] Send e-mail') print('[2] Sell') print('[3] Send e-mail and sell') self.actions_selection = input() if self.actions_selection == '1': self.actions.append(Alert.ACTION_SEND_EMAIL) if self.actions_selection == '2': self.actions.append(Alert.ACTION_SELL_ASSET) elif self.actions_selection == '3': self.actions.extend( [Alert.ACTION_SEND_EMAIL, Alert.ACTION_SELL_ASSET]) if self._client is None: self._client = BitvavoClient(market=self.market) self.alert = Alert(actions=self.actions, init_price=self.alert_init_price, trailing_percentage=self.alert_trailing_percentage, market=self.market, _client=self._client) if not self.alert.init_attributes(): print('Error occurred.') self.save_alert() print('New alert created.') print(self.alert.attributes())
from models.CreateAlert import CreateAlert from models.clients.Bitvavo import BitvavoClient if __name__ == '__main__': ca = CreateAlert(_client=BitvavoClient()) ca.add_by_console()