Example #1
0
    def __init__(
        self,
        name,
        config=None,
        onAccount=None,
        onOrderMatched=None,
        onOrderPlaced=None,
        onMarketUpdate=None,
        onUpdateCallOrder=None,
        ontick=None,
        bitshares_instance=None,
        *args,
        **kwargs
    ):

        BitsharesOrderEngine.__init__(self, name, config=config, *args, **kwargs)

        if ontick:
            self.ontick += ontick
        if onMarketUpdate:
            self.onMarketUpdate += onMarketUpdate
        if onAccount:
            self.onAccount += onAccount
        if onOrderMatched:
            self.onOrderMatched += onOrderMatched
        if onOrderPlaced:
            self.onOrderPlaced += onOrderPlaced
        if onUpdateCallOrder:
            self.onUpdateCallOrder += onUpdateCallOrder

        # Redirect this event to also call order placed and order matched
        self.onMarketUpdate += self._callbackPlaceFillOrders

        self.assets_intersections_data = None
        if config:
            self.config = config
            self.assets_intersections_data = Config.assets_intersections(config)
        else:
            self.config = config = Config.get_worker_config_file(name)

        # What percent of balance the worker should use
        self.operational_percent_quote = self.worker.get('operational_percent_quote', 0) / 100
        self.operational_percent_base = self.worker.get('operational_percent_base', 0) / 100

        # Initial value for check_last_run decorator in dexbot/decorators.py
        self.last_check = datetime(1970, 1, 1)

        # A private logger that adds worker identify data to the LogRecord
        self.log = logging.LoggerAdapter(
            logging.getLogger('dexbot.per_worker'),
            {
                'worker_name': name,
                'account': self.worker['account'],
                'market': self.worker['market'],
                'is_disabled': lambda: self.disabled,
            },
        )

        self.orders_log = logging.LoggerAdapter(logging.getLogger('dexbot.orders_log'), {})
Example #2
0
    def validate_account_not_in_use(account):
        """ Check whether account is already used for another worker or not

            :param str account: bitshares account name
        """
        workers = Config().workers_data
        for worker_name, worker in workers.items():
            if worker['account'] == account:
                return False
        return True
Example #3
0
File: ui.py Project: tryiou/DEXBot
 def new_func(ctx, *args, **kwargs):
     if not os.path.isfile(ctx.obj["configfile"]):
         Config(path=ctx.obj['configfile'])
     ctx.config = yaml.safe_load(open(ctx.obj["configfile"]))
     # reset to default
     ctx.config["node"] = Config().node_list
     if ctx.obj.get("sortnodes"):
         nodelist = sort_nodes(ctx)
         # sort nodes if option is given
         ctx.config["node"] = nodelist
     with open(ctx.obj["configfile"], 'w') as file:
         yaml.dump(ctx.config, file, default_flow_style=False)
     return ctx.invoke(f, *args, **kwargs)
Example #4
0
def configure(ctx):
    """Interactively configure dexbot."""
    # Make sure the dexbot service isn't running while we do the config edits
    if dexbot_service_running():
        click.echo("Stopping dexbot daemon")
        os.system('systemctl --user stop dexbot')

    config = Config(path=ctx.obj['configfile'])
    configure_dexbot(config, ctx)
    config.save_config()

    click.echo("New configuration saved")
    if config.get('systemd_status', 'disabled') == 'enabled':
        click.echo("Starting dexbot daemon")
        os.system("systemctl --user start dexbot")
Example #5
0
    def __init__(self,
                 name,
                 config=None,
                 _account=None,
                 _market=None,
                 fee_asset_symbol=None,
                 bitshares_instance=None,
                 bitshares_bundle=None,
                 *args,
                 **kwargs):

        # BitShares instance
        self.bitshares = bitshares_instance or shared_bitshares_instance()

        # Dex instance used to get different fees for the market
        self.dex = Dex(self.bitshares)

        # Storage
        Storage.__init__(self, name)

        # Events
        Events.__init__(self)

        # Redirect this event to also call order placed and order matched
        self.onMarketUpdate += self._callbackPlaceFillOrders

        if config:
            self.config = config
        else:
            self.config = Config.get_worker_config_file(name)

        self._market = _market
        self._account = _account

        # Recheck flag - Tell the strategy to check for updated orders
        self.recheck_orders = False

        # Count of orders to be fetched from the API
        self.fetch_depth = 8

        self.fee_asset = fee_asset_symbol

        # CER cache
        self.core_exchange_rate = None

        # Ticker
        self.ticker = self._market.ticker

        # Settings for bitshares instance
        self.bitshares.bundle = bitshares_bundle

        # Disabled flag - this flag can be flipped to True by a worker and will be reset to False after reset only
        self.disabled = False

        # Order expiration time in seconds
        self.expiration = 60 * 60 * 24 * 365 * 5

        # buy/sell actions will return order id by default
        self.returnOrderId = 'head'
Example #6
0
 def validate_worker_name(cls, worker_name, old_worker_name=None):
     if old_worker_name != worker_name:
         worker_names = Config().workers_data.keys()
         # Check that the name is unique
         if worker_name in worker_names:
             return False
         return True
     return True
Example #7
0
    def handle_open_settings(self):
        settings_dialog = SettingsView()
        reconnect = settings_dialog.exec_()

        if reconnect:
            # Reinitialize config after closing the settings window
            self.config = Config()
            self.main_controller.config = self.config

            self.connect_to_bitshares()
Example #8
0
    def get_unique_worker_name():
        """ Returns unique worker name "Worker %n", where %n is the next available index
        """
        index = 1
        workers = Config().workers_data.keys()
        worker_name = "Worker {0}".format(index)
        while worker_name in workers:
            worker_name = "Worker {0}".format(index)
            index += 1

        return worker_name
Example #9
0
    def validate_worker_name(worker_name, old_worker_name=None):
        """ Check whether worker name is unique or not

            :param str worker_name: name of the new worker
            :param str old_worker_name: old name of the worker
        """
        if old_worker_name != worker_name:
            worker_names = Config().workers_data.keys()
            # Check that the name is unique
            if worker_name in worker_names:
                return False
            return True
        return True
Example #10
0
    def __init__(self, sys_argv):
        super(App, self).__init__(sys_argv)

        # Init config
        config = Config()

        # Init main controller
        self.main_controller = MainController(config)

        # Init main view
        self.main_view = MainView(self.main_controller)

        # Show main view
        self.main_view.show()
Example #11
0
    def __init__(self, sys_argv):
        super(App, self).__init__(sys_argv)

        config = Config()
        bitshares_instance = BitShares(config['node'])

        # Wallet unlock
        unlock_ctrl = WalletController(bitshares_instance)
        if unlock_ctrl.wallet_created():
            unlock_view = UnlockWalletView(unlock_ctrl)
        else:
            unlock_view = CreateWalletView(unlock_ctrl)

        if unlock_view.exec_():
            bitshares_instance = unlock_ctrl.bitshares
            self.main_ctrl = MainController(bitshares_instance, config)
            self.main_view = MainView(self.main_ctrl)
            self.main_view.show()
        else:
            sys.exit()
Example #12
0
File: cli.py Project: lafona/DEXBot
def shell():
    """ Run dexbot as a shell
    """
    config = Config()
    while True:
        if configure_dexbot(config, True):
            if config['systemd_status'] == 'installed':
                config.save_config()
                # we are already installed
                os.system("systemctl --user restart dexbot")
            if config['systemd_status'] == 'install':
                config['systemd_status'] = 'installed'
                config.save_config()
                os.system("systemctl --user enable dexbot")
                os.system("systemctl --user start dexbot")
Example #13
0
File: cli.py Project: lafona/DEXBot
def configure(ctx):
    """ Interactively configure dexbot
    """
    config = Config(path=ctx.obj['configfile'])
    if configure_dexbot(config):
        if config['systemd_status'] == 'installed':
            # we are already installed
            config.save_config()
            os.system("systemctl --user restart dexbot")
        if config['systemd_status'] == 'install':
            config['systemd_status'] = 'installed'
            config.save_config()
            os.system("systemctl --user enable dexbot")
            os.system("systemctl --user start dexbot")
        click.echo("New configuration saved")
Example #14
0
 def __init__(self, view, bitshares_instance, mode):
     self.view = view
     self.mode = mode
     self.validator = ConfigValidator(Config(), bitshares_instance or shared_bitshares_instance())
Example #15
0
 def is_account_in_use(account):
     workers = Config().workers_data
     for worker_name, worker in workers.items():
         if worker['account'] == account:
             return True
     return False
Example #16
0
 def is_worker_name_valid(worker_name):
     worker_names = Config().workers_data.keys()
     # Check that the name is unique
     if worker_name in worker_names:
         return False
     return True
Example #17
0
 def __init__(self, view):
     self.config = Config()
     self.view = view
Example #18
0
class SettingsController:
    def __init__(self, view):
        self.config = Config()
        self.view = view

    def add_node(self):
        """  Add item in the widget tree list
        """
        item = QTreeWidgetItem(self.view.nodes_tree_widget)
        item.setText(0, '')
        item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled
                      | Qt.ItemIsEditable)

        # Scroll to the new item and activate editing
        self.view.nodes_tree_widget.scrollToItem(item)
        self.view.nodes_tree_widget.editItem(item)

        self.view.notification_label.setText(
            'Unsaved changes detected; Node added.')

    def move_up(self):
        """  Move item up in the widget tree list
        """
        current_index = self.view.nodes_tree_widget.indexOfTopLevelItem(
            self.view.nodes_tree_widget.currentItem())

        # This prevents moving item out of the list
        if current_index > 0:
            # Take the item out of the widget list
            item = self.view.nodes_tree_widget.takeTopLevelItem(current_index)

            # Put item back to the list in new position
            self.view.root_item.insertChild(current_index - 1, item)

            # Keep moved item selected
            self.view.nodes_tree_widget.setCurrentItem(item)
            self.view.notification_label.setText(
                'Unsaved changes detected; List order has changed.')

    def move_down(self):
        """  Move item down in the widget tree list
        """
        current_index = self.view.nodes_tree_widget.indexOfTopLevelItem(
            self.view.nodes_tree_widget.currentItem())

        # This prevents moving item out of the list
        if current_index < (self.view.root_item.childCount() - 1):
            # Take the item out of the widget list
            item = self.view.nodes_tree_widget.takeTopLevelItem(current_index)

            # Put item back to the list in new position
            self.view.root_item.insertChild(current_index + 1, item)

            # Keep moved item selected
            self.view.nodes_tree_widget.setCurrentItem(item)
            self.view.notification_label.setText(
                'Unsaved changes detected; List order has changed.')

    def save_settings(self):
        """  Save items in the tree widget list into the config file and close window

            :returns int: 1 settings saved (accepted)
        """
        nodes = []

        child_count = self.view.root_item.childCount()

        for index in range(child_count):
            nodes.append(self.view.root_item.child(index).text(0))

        # Send the nodes to controller to handle the save
        if self.save_nodes_to_config(nodes):

            # Close settings dialog on save
            self.view.accept()

    def remove_node(self):
        """  Remove item from the widget tree list
        """
        node = self.view.nodes_tree_widget.currentItem()

        if node:
            # Delete only if node selected,
            index = self.view.nodes_tree_widget.indexOfTopLevelItem(node)
            self.view.nodes_tree_widget.takeTopLevelItem(index)
            self.view.notification_label.setText(
                'Unsaved changes detected; Node removed.')

    def initialize_node_list(self, nodes=None):
        """ Populates Tree Widget with nodes

            :param nodes: List of nodes that can be applied to the widget instead of getting them from the config file.
        """
        # Make sure there are no widgets in the list
        self.view.nodes_tree_widget.clear()

        # Get nodes from the config file
        if nodes is None:
            nodes = self.view.controller.nodes

        # Check for nodes, since it is possible that the config is empty
        if nodes:
            # Add nodes to the widget list
            for node in nodes:
                item = QTreeWidgetItem(self.view.nodes_tree_widget)
                item.setText(0, node)
                item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled
                              | Qt.ItemIsEditable)

    def save_nodes_to_config(self, nodes):
        """ Save nodes to the config file
        """
        # Remove empty nodes before saving, this is just to make sure no empty strings end up in config file
        nodes = self.remove_empty_items(nodes)

        if nodes:
            self.config['node'] = nodes
            self.config.save_config()
            # Update status
            self.view.notification_label.setText(
                'Settings successfully saved!')
            return True
        else:
            self.view.notification_label.setText('Can\'t save empty list')
            return False

    def restore_defaults(self):
        self.initialize_node_list(nodes=self.config.node_list)
        self.view.notification_label.setText(
            'Restored default nodes. Remember to save changes!')

    @staticmethod
    def remove_empty_items(items):
        """ Removes empty strings from a list
        """
        return list(filter(None, items))

    @property
    def nodes(self):
        """ Returns nodes list from the config file

            :return: Nodes list
        """
        return self.config.get('node')
Example #19
0
    def __init__(
        self,
        name,
        config=None,
        _account=None,
        _market=None,
        fee_asset_symbol=None,
        bitshares_instance=None,
        *args,
        **kwargs
    ):

        # BitShares instance
        self.bitshares = bitshares_instance or shared_bitshares_instance()

        # Dex instance used to get different fees for the market
        self.dex = Dex(self.bitshares)

        # Storage
        Storage.__init__(self, name)

        # Events
        Events.__init__(self)

        # Redirect this event to also call order placed and order matched
        self.onMarketUpdate += self._callbackPlaceFillOrders

        if config:
            self.config = config
        else:
            self.config = Config.get_worker_config_file(name)

        # Get worker's parameters from the config
        self.worker = config["workers"][name]
        self._market = _market or Market(self.worker["market"], bitshares_instance=self.bitshares)
        self._account = _account or Account(self.worker["account"], full=True, bitshares_instance=self.bitshares)

        # Recheck flag - Tell the strategy to check for updated orders
        self.recheck_orders = False

        # Count of orders to be fetched from the API
        self.fetch_depth = 8

        # Set fee asset
        fee_asset_symbol = fee_asset_symbol or self.worker.get('fee_asset')

        if fee_asset_symbol:
            try:
                self.fee_asset = Asset(fee_asset_symbol, bitshares_instance=self.bitshares)
            except bitshares.exceptions.AssetDoesNotExistsException:
                self.fee_asset = Asset('1.3.0', bitshares_instance=self.bitshares)
        else:
            # If there is no fee asset, use BTS
            self.fee_asset = Asset('1.3.0', bitshares_instance=self.bitshares)

        # CER cache
        self.core_exchange_rate = None

        # Ticker
        self.ticker = self._market.ticker

        # Settings for bitshares instance
        self.bitshares.bundle = bool(self.worker.get("bundle", False))

        # Disabled flag - this flag can be flipped to True by a worker and will be reset to False after reset only
        self.disabled = False

        # Order expiration time in seconds
        self.expiration = 60 * 60 * 24 * 365 * 5

        # buy/sell actions will return order id by default
        self.returnOrderId = 'head'

        self.log = logging.LoggerAdapter(logging.getLogger('dexbot.orderengine'), {})
Example #20
0
 def new_func(ctx, *args, **kwargs):
     if not os.path.isfile(ctx.obj["configfile"]):
         Config(path=ctx.obj['configfile'])
     ctx.config = yaml.safe_load(open(ctx.obj["configfile"]))
     return ctx.invoke(f, *args, **kwargs)
Example #21
0
    def __init__(self,
                 name,
                 config=None,
                 onAccount=None,
                 onOrderMatched=None,
                 onOrderPlaced=None,
                 onMarketUpdate=None,
                 onUpdateCallOrder=None,
                 ontick=None,
                 bitshares_instance=None,
                 *args,
                 **kwargs):

        # BitShares instance
        self.bitshares = bitshares_instance or shared_bitshares_instance()

        # Storage
        Storage.__init__(self, name)

        # Events
        Events.__init__(self)

        if ontick:
            self.ontick += ontick
        if onMarketUpdate:
            self.onMarketUpdate += onMarketUpdate
        if onAccount:
            self.onAccount += onAccount
        if onOrderMatched:
            self.onOrderMatched += onOrderMatched
        if onOrderPlaced:
            self.onOrderPlaced += onOrderPlaced
        if onUpdateCallOrder:
            self.onUpdateCallOrder += onUpdateCallOrder

        # Redirect this event to also call order placed and order matched
        self.onMarketUpdate += self._callbackPlaceFillOrders

        self.assets_intersections_data = None
        if config:
            self.config = config
            self.assets_intersections_data = Config.assets_intersections(
                config)
        else:
            self.config = config = Config.get_worker_config_file(name)

        # Get worker's parameters from the config
        self.worker = config["workers"][name]

        # Recheck flag - Tell the strategy to check for updated orders
        self.recheck_orders = False

        # Count of orders to be fetched from the API
        self.fetch_depth = 8

        # What percent of balance the worker should use
        self.operational_percent_quote = self.worker.get(
            'operational_percent_quote', 0) / 100
        self.operational_percent_base = self.worker.get(
            'operational_percent_base', 0) / 100

        # Get Bitshares account and market for this worker
        self._account = Account(self.worker["account"],
                                full=True,
                                bitshares_instance=self.bitshares)
        self._market = Market(config["workers"][name]["market"],
                              bitshares_instance=self.bitshares)

        # Set fee asset
        fee_asset_symbol = self.worker.get('fee_asset')

        if fee_asset_symbol:
            try:
                self.fee_asset = Asset(fee_asset_symbol,
                                       bitshares_instance=self.bitshares)
            except bitshares.exceptions.AssetDoesNotExistsException:
                self.fee_asset = Asset('1.3.0',
                                       bitshares_instance=self.bitshares)
        else:
            # If there is no fee asset, use BTS
            self.fee_asset = Asset('1.3.0', bitshares_instance=self.bitshares)

        # CER cache
        self.core_exchange_rate = None

        # Ticker
        self.ticker = self._market.ticker

        # Settings for bitshares instance
        self.bitshares.bundle = bool(self.worker.get("bundle", False))

        # Disabled flag - this flag can be flipped to True by a worker and will be reset to False after reset only
        self.disabled = False

        # Order expiration time in seconds
        self.expiration = 60 * 60 * 24 * 365 * 5

        # buy/sell actions will return order id by default
        self.returnOrderId = 'head'

        # A private logger that adds worker identify data to the LogRecord
        self.log = logging.LoggerAdapter(
            logging.getLogger('dexbot.per_worker'), {
                'worker_name': name,
                'account': self.worker['account'],
                'market': self.worker['market'],
                'is_disabled': lambda: self.disabled
            })

        self.orders_log = logging.LoggerAdapter(
            logging.getLogger('dexbot.orders_log'), {})
Example #22
0
 def validate_account_not_in_use(cls, account):
     workers = Config().workers_data
     for worker_name, worker in workers.items():
         if worker['account'] == account:
             return False
     return True