예제 #1
0
    def __init__(self, args: list, **kwargs):
        parser = argparse.ArgumentParser(prog='gateio-market-maker-keeper')

        parser.add_argument("--gateio-api-server", type=str, default="https://data.gate.io",
                            help="Address of the Gate.io API server (default: 'https://data.gate.io')")

        parser.add_argument("--gateio-api-key", type=str, required=True,
                            help="API key for the Gate.io API")

        parser.add_argument("--gateio-secret-key", type=str, required=True,
                            help="Secret key for the Gate.io API")

        parser.add_argument("--gateio-timeout", type=float, default=9.5,
                            help="Timeout for accessing the Gate.io API (in seconds, default: 9.5)")

        parser.add_argument("--pair", type=str, required=True,
                            help="Token pair on which the keeper should operate")

        parser.add_argument("--config", type=str, required=True,
                            help="Buy/sell bands configuration file")

        parser.add_argument("--price-feed", type=str,
                            help="Source of price feed")

        parser.add_argument("--price-feed-expiry", type=int, default=120,
                            help="Maximum age of the price feed (in seconds, default: 120)")

        parser.add_argument("--debug", dest='debug', action='store_true',
                            help="Enable debug output")

        self.arguments = parser.parse_args(args)

        logging.basicConfig(format='%(asctime)-15s %(levelname)-8s %(message)s',
                            level=(logging.DEBUG if self.arguments.debug else logging.INFO))
        logging.getLogger('urllib3.connectionpool').setLevel(logging.INFO)
        logging.getLogger('requests.packages.urllib3.connectionpool').setLevel(logging.INFO)

        self.bands_config = ReloadableConfig(self.arguments.config)
        self.price_feed = PriceFeedFactory().create_price_feed(self.arguments.price_feed, self.arguments.price_feed_expiry)

        self.gateio_api = GateIOApi(api_server=self.arguments.gateio_api_server,
                                    api_key=self.arguments.gateio_api_key,
                                    secret_key=self.arguments.gateio_secret_key,
                                    timeout=self.arguments.gateio_timeout)

        self._last_order_creation = 0
    def __init__(self, args: list):
        parser = argparse.ArgumentParser(prog='gateio-market-maker-keeper')

        parser.add_argument("--gateio-api-server", type=str, default="https://data.gate.io",
                            help="Address of the Gate.io API server (default: 'https://data.gate.io')")

        parser.add_argument("--gateio-api-key", type=str, required=True,
                            help="API key for the Gate.io API")

        parser.add_argument("--gateio-secret-key", type=str, required=True,
                            help="Secret key for the Gate.io API")

        parser.add_argument("--gateio-timeout", type=float, default=9.5,
                            help="Timeout for accessing the Gate.io API (in seconds, default: 9.5)")

        parser.add_argument("--pair", type=str, required=True,
                            help="Token pair (sell/buy) on which the keeper will operate")

        parser.add_argument("--config", type=str, required=True,
                            help="Bands configuration file")

        parser.add_argument("--price-feed", type=str, required=True,
                            help="Source of price feed")

        parser.add_argument("--price-feed-expiry", type=int, default=120,
                            help="Maximum age of the price feed (in seconds, default: 120)")

        parser.add_argument("--spread-feed", type=str,
                            help="Source of spread feed")

        parser.add_argument("--spread-feed-expiry", type=int, default=3600,
                            help="Maximum age of the spread feed (in seconds, default: 3600)")

        parser.add_argument("--order-history", type=str,
                            help="Endpoint to report active orders to")

        parser.add_argument("--order-history-every", type=int, default=30,
                            help="Frequency of reporting active orders (in seconds, default: 30)")

        parser.add_argument("--debug", dest='debug', action='store_true',
                            help="Enable debug output")

        self.arguments = parser.parse_args(args)
        setup_logging(self.arguments)

        self.bands_config = ReloadableConfig(self.arguments.config)
        self.price_feed = PriceFeedFactory().create_price_feed(self.arguments)
        self.spread_feed = create_spread_feed(self.arguments)
        self.order_history_reporter = create_order_history_reporter(self.arguments)

        self.history = History()
        self.gateio_api = GateIOApi(api_server=self.arguments.gateio_api_server,
                                    api_key=self.arguments.gateio_api_key,
                                    secret_key=self.arguments.gateio_secret_key,
                                    timeout=self.arguments.gateio_timeout)

        self._last_order_creation = 0
예제 #3
0
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import sys

from pyexchange.gateio import GateIOApi
from pymaker.numeric import Wad

gate = GateIOApi('https://data.gate.io', sys.argv[1], sys.argv[2], 9.5)

# print(gate.pairs())
# print(gate.tickers())
# print(gate.ticker('mkr_eth'))
# print(gate.orderBooks())
# print(gate.order_book('btc_usdt'))
# print(gate.get_balances())
#{'result': 'true', 'message': 'Success', 'code': 0, 'orderNumber': 368042106}
# print(gate.place_order('mkr_eth', False, Wad.from_number(1.35), Wad.from_number(0.01)))
# print(gate.place_order('mkr_eth', True, Wad.from_number(1.45), Wad.from_number(0.01)))
# print(gate.sell('etc_btc','0.001','123'))
# print(gate.getOrder('267040896','eth_btc'))
# print(gate.get_orders('mkr_eth'))
# for order in gate.get_orders('mkr_eth'):
#     print(gate.cancel_order('mkr_eth', order.order_id))
    def __init__(self, args: list):
        parser = argparse.ArgumentParser(prog='gateio-market-maker-keeper')

        parser.add_argument(
            "--gateio-api-server",
            type=str,
            default="https://data.gate.io",
            help=
            "Address of the Gate.io API server (default: 'https://data.gate.io')"
        )

        parser.add_argument("--gateio-api-key",
                            type=str,
                            required=True,
                            help="API key for the Gate.io API")

        parser.add_argument("--gateio-secret-key",
                            type=str,
                            required=True,
                            help="Secret key for the Gate.io API")

        parser.add_argument(
            "--gateio-timeout",
            type=float,
            default=9.5,
            help=
            "Timeout for accessing the Gate.io API (in seconds, default: 9.5)")

        parser.add_argument(
            "--pair",
            type=str,
            required=True,
            help="Token pair (sell/buy) on which the keeper will operate")

        parser.add_argument("--config",
                            type=str,
                            required=True,
                            help="Bands configuration file")

        parser.add_argument("--price-feed",
                            type=str,
                            required=True,
                            help="Source of price feed")

        parser.add_argument(
            "--price-feed-expiry",
            type=int,
            default=120,
            help="Maximum age of the price feed (in seconds, default: 120)")

        parser.add_argument("--spread-feed",
                            type=str,
                            help="Source of spread feed")

        parser.add_argument(
            "--spread-feed-expiry",
            type=int,
            default=3600,
            help="Maximum age of the spread feed (in seconds, default: 3600)")

        parser.add_argument("--order-history",
                            type=str,
                            help="Endpoint to report active orders to")

        parser.add_argument(
            "--order-history-every",
            type=int,
            default=30,
            help=
            "Frequency of reporting active orders (in seconds, default: 30)")

        parser.add_argument(
            "--refresh-frequency",
            type=int,
            default=3,
            help="Order book refresh frequency (in seconds, default: 3)")

        parser.add_argument("--debug",
                            dest='debug',
                            action='store_true',
                            help="Enable debug output")

        self.arguments = parser.parse_args(args)
        setup_logging(self.arguments)

        self.bands_config = ReloadableConfig(self.arguments.config)
        self.price_feed = PriceFeedFactory().create_price_feed(self.arguments)
        self.spread_feed = create_spread_feed(self.arguments)
        self.order_history_reporter = create_order_history_reporter(
            self.arguments)

        self.history = History()
        self.gateio_api = GateIOApi(
            api_server=self.arguments.gateio_api_server,
            api_key=self.arguments.gateio_api_key,
            secret_key=self.arguments.gateio_secret_key,
            timeout=self.arguments.gateio_timeout)

        self.order_book_manager = OrderBookManager(
            refresh_frequency=self.arguments.refresh_frequency)
        self.order_book_manager.get_orders_with(
            lambda: self.gateio_api.get_orders(self.pair()))
        self.order_book_manager.get_balances_with(
            lambda: self.gateio_api.get_balances())
        self.order_book_manager.cancel_orders_with(
            lambda order: self.gateio_api.cancel_order(self.pair(), order.
                                                       order_id))
        self.order_book_manager.enable_history_reporting(
            self.order_history_reporter, self.our_buy_orders,
            self.our_sell_orders)
        self.order_book_manager.start()

        self._last_order_creation = 0
class GateIOMarketMakerKeeper:
    """Keeper acting as a market maker on Gate.io."""

    logger = logging.getLogger()

    def __init__(self, args: list):
        parser = argparse.ArgumentParser(prog='gateio-market-maker-keeper')

        parser.add_argument(
            "--gateio-api-server",
            type=str,
            default="https://data.gate.io",
            help=
            "Address of the Gate.io API server (default: 'https://data.gate.io')"
        )

        parser.add_argument("--gateio-api-key",
                            type=str,
                            required=True,
                            help="API key for the Gate.io API")

        parser.add_argument("--gateio-secret-key",
                            type=str,
                            required=True,
                            help="Secret key for the Gate.io API")

        parser.add_argument(
            "--gateio-timeout",
            type=float,
            default=9.5,
            help=
            "Timeout for accessing the Gate.io API (in seconds, default: 9.5)")

        parser.add_argument(
            "--pair",
            type=str,
            required=True,
            help="Token pair (sell/buy) on which the keeper will operate")

        parser.add_argument("--config",
                            type=str,
                            required=True,
                            help="Bands configuration file")

        parser.add_argument("--price-feed",
                            type=str,
                            required=True,
                            help="Source of price feed")

        parser.add_argument(
            "--price-feed-expiry",
            type=int,
            default=120,
            help="Maximum age of the price feed (in seconds, default: 120)")

        parser.add_argument("--spread-feed",
                            type=str,
                            help="Source of spread feed")

        parser.add_argument(
            "--spread-feed-expiry",
            type=int,
            default=3600,
            help="Maximum age of the spread feed (in seconds, default: 3600)")

        parser.add_argument("--order-history",
                            type=str,
                            help="Endpoint to report active orders to")

        parser.add_argument(
            "--order-history-every",
            type=int,
            default=30,
            help=
            "Frequency of reporting active orders (in seconds, default: 30)")

        parser.add_argument(
            "--refresh-frequency",
            type=int,
            default=3,
            help="Order book refresh frequency (in seconds, default: 3)")

        parser.add_argument("--debug",
                            dest='debug',
                            action='store_true',
                            help="Enable debug output")

        self.arguments = parser.parse_args(args)
        setup_logging(self.arguments)

        self.bands_config = ReloadableConfig(self.arguments.config)
        self.price_feed = PriceFeedFactory().create_price_feed(self.arguments)
        self.spread_feed = create_spread_feed(self.arguments)
        self.order_history_reporter = create_order_history_reporter(
            self.arguments)

        self.history = History()
        self.gateio_api = GateIOApi(
            api_server=self.arguments.gateio_api_server,
            api_key=self.arguments.gateio_api_key,
            secret_key=self.arguments.gateio_secret_key,
            timeout=self.arguments.gateio_timeout)

        self.order_book_manager = OrderBookManager(
            refresh_frequency=self.arguments.refresh_frequency)
        self.order_book_manager.get_orders_with(
            lambda: self.gateio_api.get_orders(self.pair()))
        self.order_book_manager.get_balances_with(
            lambda: self.gateio_api.get_balances())
        self.order_book_manager.cancel_orders_with(
            lambda order: self.gateio_api.cancel_order(self.pair(), order.
                                                       order_id))
        self.order_book_manager.enable_history_reporting(
            self.order_history_reporter, self.our_buy_orders,
            self.our_sell_orders)
        self.order_book_manager.start()

        self._last_order_creation = 0

    def main(self):
        with Lifecycle() as lifecycle:
            lifecycle.initial_delay(10)
            lifecycle.every(1, self.synchronize_orders)
            lifecycle.on_shutdown(self.shutdown)

    def shutdown(self):
        self.order_book_manager.cancel_all_orders()

    def pair(self):
        return self.arguments.pair.lower()

    def token_sell(self) -> str:
        return self.arguments.pair.split('_')[0].upper()

    def token_buy(self) -> str:
        return self.arguments.pair.split('_')[1].upper()

    def our_available_balance(self, our_balances: dict, token: str) -> Wad:
        try:
            return Wad.from_number(our_balances['available'][token])
        except KeyError:
            return Wad(0)

    def our_sell_orders(self, our_orders: list) -> list:
        return list(filter(lambda order: order.is_sell, our_orders))

    def our_buy_orders(self, our_orders: list) -> list:
        return list(filter(lambda order: not order.is_sell, our_orders))

    def synchronize_orders(self):
        bands = Bands.read(self.bands_config, self.spread_feed, self.history)
        order_book = self.order_book_manager.get_order_book()
        target_price = self.price_feed.get_price()

        # Cancel orders
        cancellable_orders = bands.cancellable_orders(
            our_buy_orders=self.our_buy_orders(order_book.orders),
            our_sell_orders=self.our_sell_orders(order_book.orders),
            target_price=target_price)
        if len(cancellable_orders) > 0:
            self.order_book_manager.cancel_orders(cancellable_orders)
            return

        # Do not place new orders if order book state is not confirmed
        if order_book.orders_being_placed or order_book.orders_being_cancelled:
            self.logger.debug(
                "Order book is in progress, not placing new orders")
            return

        # Place new orders
        new_orders = bands.new_orders(
            our_buy_orders=self.our_buy_orders(order_book.orders),
            our_sell_orders=self.our_sell_orders(order_book.orders),
            our_buy_balance=self.our_available_balance(order_book.balances,
                                                       self.token_buy()),
            our_sell_balance=self.our_available_balance(
                order_book.balances, self.token_sell()),
            target_price=target_price)[0]

        if len(new_orders) > 0:
            if self.can_create_orders():
                self.place_orders(new_orders)
                self.register_order_creation()
            else:
                self.logger.info(
                    "Too little time elapsed from last order creation, waiting..."
                )

    # Unfortunately the gate.io API does not immediately reflect the fact that our orders have
    # been placed. In order to avoid placing orders twice we explicitly wait some time here.
    def can_create_orders(self) -> bool:
        return time.time() - self._last_order_creation > 15

    def register_order_creation(self):
        self._last_order_creation = time.time()

    def place_orders(self, new_orders: List[NewOrder]):
        def place_order_function(new_order_to_be_placed):
            amount = new_order_to_be_placed.pay_amount if new_order_to_be_placed.is_sell else new_order_to_be_placed.buy_amount
            order_id = self.gateio_api.place_order(
                self.pair(), new_order_to_be_placed.is_sell,
                new_order_to_be_placed.price, amount)

            return Order(order_id=order_id,
                         timestamp=0,
                         pair=self.pair(),
                         is_sell=new_order_to_be_placed.is_sell,
                         price=new_order_to_be_placed.price,
                         amount=amount,
                         amount_symbol=self.token_sell(),
                         money=amount * new_order_to_be_placed.price,
                         money_symbol=self.token_buy(),
                         initial_amount=amount,
                         filled_amount=Wad(0))

        for new_order in new_orders:
            self.order_book_manager.place_order(
                lambda new_order=new_order: place_order_function(new_order))
예제 #6
0
    def __init__(self, args: list, **kwargs):
        parser = argparse.ArgumentParser(prog='gateio-market-maker-keeper')

        parser.add_argument(
            "--gateio-api-server",
            type=str,
            default="https://data.gate.io",
            help=
            "Address of the Gate.io API server (default: 'https://data.gate.io')"
        )

        parser.add_argument("--gateio-api-key",
                            type=str,
                            required=True,
                            help="API key for the Gate.io API")

        parser.add_argument("--gateio-secret-key",
                            type=str,
                            required=True,
                            help="Secret key for the Gate.io API")

        parser.add_argument(
            "--gateio-timeout",
            type=float,
            default=9.5,
            help=
            "Timeout for accessing the Gate.io API (in seconds, default: 9.5)")

        parser.add_argument(
            "--pair",
            type=str,
            required=True,
            help="Token pair (sell/buy) on which the keeper will operate")

        parser.add_argument("--config",
                            type=str,
                            required=True,
                            help="Bands configuration file")

        parser.add_argument("--price-feed",
                            type=str,
                            required=True,
                            help="Source of price feed")

        parser.add_argument(
            "--price-feed-expiry",
            type=int,
            default=120,
            help="Maximum age of the price feed (in seconds, default: 120)")

        parser.add_argument("--debug",
                            dest='debug',
                            action='store_true',
                            help="Enable debug output")

        self.arguments = parser.parse_args(args)
        setup_logging(self.arguments)

        self.bands_config = ReloadableConfig(self.arguments.config)
        self.price_feed = PriceFeedFactory().create_price_feed(
            self.arguments.price_feed, self.arguments.price_feed_expiry)

        self.gateio_api = GateIOApi(
            api_server=self.arguments.gateio_api_server,
            api_key=self.arguments.gateio_api_key,
            secret_key=self.arguments.gateio_secret_key,
            timeout=self.arguments.gateio_timeout)

        self._last_order_creation = 0
예제 #7
0
class GateIOMarketMakerKeeper:
    """Keeper acting as a market maker on Gate.io."""

    logger = logging.getLogger()

    def __init__(self, args: list, **kwargs):
        parser = argparse.ArgumentParser(prog='gateio-market-maker-keeper')

        parser.add_argument(
            "--gateio-api-server",
            type=str,
            default="https://data.gate.io",
            help=
            "Address of the Gate.io API server (default: 'https://data.gate.io')"
        )

        parser.add_argument("--gateio-api-key",
                            type=str,
                            required=True,
                            help="API key for the Gate.io API")

        parser.add_argument("--gateio-secret-key",
                            type=str,
                            required=True,
                            help="Secret key for the Gate.io API")

        parser.add_argument(
            "--gateio-timeout",
            type=float,
            default=9.5,
            help=
            "Timeout for accessing the Gate.io API (in seconds, default: 9.5)")

        parser.add_argument(
            "--pair",
            type=str,
            required=True,
            help="Token pair (sell/buy) on which the keeper will operate")

        parser.add_argument("--config",
                            type=str,
                            required=True,
                            help="Bands configuration file")

        parser.add_argument("--price-feed",
                            type=str,
                            required=True,
                            help="Source of price feed")

        parser.add_argument(
            "--price-feed-expiry",
            type=int,
            default=120,
            help="Maximum age of the price feed (in seconds, default: 120)")

        parser.add_argument("--debug",
                            dest='debug',
                            action='store_true',
                            help="Enable debug output")

        self.arguments = parser.parse_args(args)
        setup_logging(self.arguments)

        self.bands_config = ReloadableConfig(self.arguments.config)
        self.price_feed = PriceFeedFactory().create_price_feed(
            self.arguments.price_feed, self.arguments.price_feed_expiry)

        self.gateio_api = GateIOApi(
            api_server=self.arguments.gateio_api_server,
            api_key=self.arguments.gateio_api_key,
            secret_key=self.arguments.gateio_secret_key,
            timeout=self.arguments.gateio_timeout)

        self._last_order_creation = 0

    def main(self):
        with Lifecycle() as lifecycle:
            lifecycle.on_startup(self.startup)
            lifecycle.every(10, self.synchronize_orders)
            lifecycle.on_shutdown(self.shutdown)

    def startup(self):
        self.our_orders()
        self.our_balances()
        self.logger.info(f"Gate.io API key seems to be valid")
        self.logger.info(
            f"Keeper configured to work on the '{self.pair()}' pair")

    def shutdown(self):
        self.gateio_api.cancel_all_orders(self.pair())

    def pair(self):
        return self.arguments.pair.lower()

    def token_sell(self) -> str:
        return self.arguments.pair.split('_')[0].upper()

    def token_buy(self) -> str:
        return self.arguments.pair.split('_')[1].upper()

    def our_balances(self) -> dict:
        return self.gateio_api.get_balances()

    def our_available_balance(self, our_balances: dict, token: str) -> Wad:
        try:
            return Wad.from_number(our_balances['available'][token])
        except KeyError:
            return Wad(0)

    def our_orders(self) -> list:
        return self.gateio_api.get_orders(self.pair())

    def our_sell_orders(self, our_orders: list) -> list:
        return list(filter(lambda order: order.is_sell, our_orders))

    def our_buy_orders(self, our_orders: list) -> list:
        return list(filter(lambda order: not order.is_sell, our_orders))

    def synchronize_orders(self):
        bands = Bands(self.bands_config)
        our_balances = self.our_balances()
        our_orders = self.our_orders()
        target_price = self.price_feed.get_price()

        if target_price is None:
            self.logger.warning(
                "Cancelling all orders as no price feed available.")
            self.cancel_orders(our_orders)
            return

        # Cancel orders
        cancellable_orders = bands.cancellable_orders(
            our_buy_orders=self.our_buy_orders(our_orders),
            our_sell_orders=self.our_sell_orders(our_orders),
            target_price=target_price)
        if len(cancellable_orders) > 0:
            self.cancel_orders(cancellable_orders)
            return

        # Place new orders
        new_orders = bands.new_orders(
            our_buy_orders=self.our_buy_orders(our_orders),
            our_sell_orders=self.our_sell_orders(our_orders),
            our_buy_balance=self.our_available_balance(our_balances,
                                                       self.token_buy()),
            our_sell_balance=self.our_available_balance(
                our_balances, self.token_sell()),
            target_price=target_price)[0]

        if len(new_orders) > 0:
            if self.can_create_orders():
                self.create_orders(new_orders)
                self.register_order_creation()
            else:
                self.logger.info(
                    "Too little time elapsed from last order creation, waiting..."
                )

    # Unfortunately the gate.io API does not immediately reflect the fact that our orders have
    # been placed. In order to avoid placing orders twice we explicitly wait some time here.
    def can_create_orders(self) -> bool:
        return time.time() - self._last_order_creation > 15

    def register_order_creation(self):
        self._last_order_creation = time.time()

    def cancel_orders(self, orders: List[Order]):
        for order in orders:
            self.gateio_api.cancel_order(self.pair(), order.order_id)

    def create_orders(self, orders: List[NewOrder]):
        for order in orders:
            amount = order.pay_amount if order.is_sell else order.buy_amount
            self.gateio_api.place_order(self.pair(), order.is_sell,
                                        order.price, amount)
class GateIOMarketMakerKeeper:
    """Keeper acting as a market maker on Gate.io."""

    logger = logging.getLogger()

    def __init__(self, args: list):
        parser = argparse.ArgumentParser(prog='gateio-market-maker-keeper')

        parser.add_argument("--gateio-api-server", type=str, default="https://data.gate.io",
                            help="Address of the Gate.io API server (default: 'https://data.gate.io')")

        parser.add_argument("--gateio-api-key", type=str, required=True,
                            help="API key for the Gate.io API")

        parser.add_argument("--gateio-secret-key", type=str, required=True,
                            help="Secret key for the Gate.io API")

        parser.add_argument("--gateio-timeout", type=float, default=9.5,
                            help="Timeout for accessing the Gate.io API (in seconds, default: 9.5)")

        parser.add_argument("--pair", type=str, required=True,
                            help="Token pair (sell/buy) on which the keeper will operate")

        parser.add_argument("--config", type=str, required=True,
                            help="Bands configuration file")

        parser.add_argument("--price-feed", type=str, required=True,
                            help="Source of price feed")

        parser.add_argument("--price-feed-expiry", type=int, default=120,
                            help="Maximum age of the price feed (in seconds, default: 120)")

        parser.add_argument("--spread-feed", type=str,
                            help="Source of spread feed")

        parser.add_argument("--spread-feed-expiry", type=int, default=3600,
                            help="Maximum age of the spread feed (in seconds, default: 3600)")

        parser.add_argument("--order-history", type=str,
                            help="Endpoint to report active orders to")

        parser.add_argument("--order-history-every", type=int, default=30,
                            help="Frequency of reporting active orders (in seconds, default: 30)")

        parser.add_argument("--debug", dest='debug', action='store_true',
                            help="Enable debug output")

        self.arguments = parser.parse_args(args)
        setup_logging(self.arguments)

        self.bands_config = ReloadableConfig(self.arguments.config)
        self.price_feed = PriceFeedFactory().create_price_feed(self.arguments)
        self.spread_feed = create_spread_feed(self.arguments)
        self.order_history_reporter = create_order_history_reporter(self.arguments)

        self.history = History()
        self.gateio_api = GateIOApi(api_server=self.arguments.gateio_api_server,
                                    api_key=self.arguments.gateio_api_key,
                                    secret_key=self.arguments.gateio_secret_key,
                                    timeout=self.arguments.gateio_timeout)

        self._last_order_creation = 0

    def main(self):
        with Lifecycle() as lifecycle:
            lifecycle.on_startup(self.startup)
            lifecycle.every(10, self.synchronize_orders)
            lifecycle.on_shutdown(self.shutdown)

    def startup(self):
        self.our_orders()
        self.our_balances()
        self.logger.info(f"Gate.io API key seems to be valid")
        self.logger.info(f"Keeper configured to work on the '{self.pair()}' pair")

    @retry(delay=5, logger=logger)
    def shutdown(self):
        self.gateio_api.cancel_all_orders(self.pair())

    def pair(self):
        return self.arguments.pair.lower()

    def token_sell(self) -> str:
        return self.arguments.pair.split('_')[0].upper()

    def token_buy(self) -> str:
        return self.arguments.pair.split('_')[1].upper()

    def our_balances(self) -> dict:
        return self.gateio_api.get_balances()

    def our_available_balance(self, our_balances: dict, token: str) -> Wad:
        try:
            return Wad.from_number(our_balances['available'][token])
        except KeyError:
            return Wad(0)

    def our_orders(self) -> list:
        return self.gateio_api.get_orders(self.pair())

    def our_sell_orders(self, our_orders: list) -> list:
        return list(filter(lambda order: order.is_sell, our_orders))

    def our_buy_orders(self, our_orders: list) -> list:
        return list(filter(lambda order: not order.is_sell, our_orders))

    def synchronize_orders(self):
        bands = Bands(self.bands_config, self.spread_feed, self.history)
        our_balances = self.our_balances()
        our_orders = self.our_orders()
        target_price = self.price_feed.get_price()

        # Cancel orders
        cancellable_orders = bands.cancellable_orders(our_buy_orders=self.our_buy_orders(our_orders),
                                                      our_sell_orders=self.our_sell_orders(our_orders),
                                                      target_price=target_price)
        if len(cancellable_orders) > 0:
            self.cancel_orders(cancellable_orders)
            return

        # Place new orders
        new_orders = bands.new_orders(our_buy_orders=self.our_buy_orders(our_orders),
                                      our_sell_orders=self.our_sell_orders(our_orders),
                                      our_buy_balance=self.our_available_balance(our_balances, self.token_buy()),
                                      our_sell_balance=self.our_available_balance(our_balances, self.token_sell()),
                                      target_price=target_price)[0]

        if len(new_orders) > 0:
            if self.can_create_orders():
                self.place_orders(new_orders)
                self.register_order_creation()
            else:
                self.logger.info("Too little time elapsed from last order creation, waiting...")

    # Unfortunately the gate.io API does not immediately reflect the fact that our orders have
    # been placed. In order to avoid placing orders twice we explicitly wait some time here.
    def can_create_orders(self) -> bool:
        return time.time() - self._last_order_creation > 15

    def register_order_creation(self):
        self._last_order_creation = time.time()

    def cancel_orders(self, orders: List[Order]):
        for order in orders:
            self.gateio_api.cancel_order(self.pair(), order.order_id)

    def place_orders(self, new_orders: List[NewOrder]):
        for new_order in new_orders:
            amount = new_order.pay_amount if new_order.is_sell else new_order.buy_amount
            self.gateio_api.place_order(self.pair(), new_order.is_sell, new_order.price, amount)
예제 #9
0
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import sys

from pyexchange.gateio import GateIOApi
from pymaker.numeric import Wad

gate = GateIOApi('https://data.gate.io', sys.argv[1], sys.argv[2], 9.5)

# print(gate.pairs())
# print(gate.tickers())
# print(gate.ticker('mkr_eth'))
# print(gate.orderBooks())
# print(gate.order_book('btc_usdt'))
# print(gate.get_balances())
#{'result': 'true', 'message': 'Success', 'code': 0, 'orderNumber': 368042106}
# print(gate.place_order('mkr_eth', False, Wad.from_number(1.35), Wad.from_number(0.01)))
# print(gate.place_order('mkr_eth', True, Wad.from_number(1.45), Wad.from_number(0.01)))
# print(gate.sell('etc_btc','0.001','123'))
# print(gate.getOrder('267040896','eth_btc'))
# print(gate.get_orders('mkr_eth'))
# for order in gate.get_orders('mkr_eth'):
#     print(gate.cancel_order('mkr_eth', order.order_id))