Beispiel #1
0
    def get_balance(self, atPrice="satoshi"):
        """
        Calcule la balance en satoshi (def), usd ou xbt atPrice.

        Si atPrice is None, use market buy sell or mid price
        Voir aussi abonnement "wallet"
        """
        satoshi_balance = self.bto.margin(
        )["availableMargin"] * self.get_leverage()
        xbt_balance = satoshi_balance * XBTSATOSHI

        if isinstance(atPrice, str):
            atPrice = atPrice.lower()
            if "usd" in atPrice:
                # renvois la balance en USD
                if "buy" in atPrice:
                    current_price = self.prices("market", "buy")
                elif "sell" in atPrice:
                    current_price = self.prices("market", "sell")
                else:
                    current_price = self.prices("midPrice")
                return round_sprice(xbt_balance * current_price, self.symbol)

            elif "xbt" in atPrice:
                return xbt_balance

        elif is_number(atPrice):
            # atPrice should be float
            return round_sprice(xbt_balance * atPrice, self.symbol)

        elif atPrice is not None:
            raise Exception("atPrice should be str number or None")

        return satoshi_balance
Beispiel #2
0
    def flexTail_offset_delta(self, refPrice=None):
        """Calcul l'offset flexible qui est fonction des variation des prix."""
        refPrice = self.get_refPrice(refPrice)
        refTail = self.get_refTail(refPrice)
        base_ofs = refTail - refPrice
        current_var, currP, prevP = self.get_current_variation()
        scale = self.get_scale(current_var)
        flexOfs = round_sprice(scale * base_ofs, self.symbol)
        # logmsg = (f'Offset_delta: prevP={round(prevP, 2)}, currP={round(currP, 2)},'
        #           f' var={round(current_var,2)}, scale={scale}, base_ofs={base_ofs},'
        #           f' flexOfs={flexOfs}, refPrice={refPrice}')

        # self.logger.debug(logmsg)
        return round_sprice(flexOfs, self.symbol), round(scale * 100, 4)
Beispiel #3
0
def amend_trailstop(brg, order, newPegOffsetValue):
    """Amend la pegOffsetValue (le delta de la sécurité (hook, crochet) par rapport au prix du marché).
    Params:
    - brg <Bargain Object>:,  - order <str>: one existing bitmex order, peut se résumé à l'essentiel {'orderID':...}
    - pegOffsetValue <int>: le delta, si >0 trigger price au dessus, (donc orderQty doit être <0 ou side sell)."""

    mlogger.info(f"order={order}, newPegOffsetValue={newPegOffsetValue}")
    newPegOffsetValue = round_sprice(newPegOffsetValue)
    return brg.bto.amend(order,
                         pegOffsetValue=newPegOffsetValue,
                         pegPriceType="TrailingStopPeg")
Beispiel #4
0
    def get_stopTail_offset_delta(self, refPrice=None, stopTail=None):
        """
        Renvois l'écart (en valeur) entre le prix de référence actuelle et la stopTail actuelle.  

        Return >0 si stopTail au dessus, <0 sinon. S'assure que les prix sont définis
        """
        refPrice = self.get_refPrice(refPrice)
        tail = self.get_data(nomElt="stopTail", default_ret=stopTail)
        if (tail - refPrice) == 0:
            return 0
        else:
            offset = round_sprice(tail - refPrice, self.symbol)
            return offset
Beispiel #5
0
def amend_stop_price(brg, orderID, newStopPx):
    """Amend the stop price of an order.
    Params:
  - brg <Bargain Object>:
- orderID <str>: one existing bitmex order,
  -newStopPx <int>: new stop price."""
    #    mlogger.debug(f'orderID={orderID}, newStopPx={newStopPx}, opts={opts}')
    newStopPx = round_sprice(newStopPx)
    try:
        order = {"orderID": orderID}  # format à vérifier pour harmonisation
        return brg.bto.amend(order, stopPx=newStopPx)
    except Exception as e:
        raise (e)
Beispiel #6
0
    def get_refTail(self, refPrice=None):
        """Renvois la queue de référence.  (la bleue).  Celle ci ne change pas d'épaisseur mais suit le prix de reférence dans ses variations.
        Elle sert à déclancher la mise à jour du stopTail lorsque la nouvelle Tail sera sortie du bois (ie assure une prise)"""
        refPrice = self.get_refPrice(refPrice)

        sens = 1 if self.head.lower() == "buy" else -1
        epaisseur = refPrice * self.tail_perct_init / 100
        ofs = -sens * epaisseur

        refTail = round_sprice(refPrice + ofs, self.symbol)

        # logmsg = f'refPrice={refPrice}, refOfs={round(ofs,2)}, sens={sens}, direction head={self.head} --> refTail={refTail}'
        # self.logger.debug(logmsg)

        return refTail
Beispiel #7
0
def place(brg, side, orderQty, price, **opts):
    """
    Place a limit order.

    - brg a Bargain,
    - side,
    - orderQty in contract,
    - price
    """
    # by default ordType='Limit'
    price = round_sprice(price)
    mlogger.debug(
        f"brg={brg}, orderQty:{orderQty}, side={side}, opts={opts}, price={price}"
    )
    return brg.bto.place(orderQty=orderQty,
                         side=side,
                         price=price,
                         asBulk=True,
                         **opts)
Beispiel #8
0
    def get_flexTail(self, refPrice=None, refTail=None):
        """
        Compute the green tail flexible tail thickness.

        C'est un nombre en minTail et maxTail qui dépend du dernier delta
        si le tableau est rempli.
        JE me base sur ça pour calculer l'offset
        """
        if pd.isna(refTail):
            refTail = self.get_refTail(refPrice)

        # if self.enought_data():
        if True:
            refPrice = self.get_refPrice(refPrice)
            flexOfs, scale = self.flexTail_offset_delta(refPrice)
            flexTail = refPrice + flexOfs

            return round_sprice(flexTail, self.symbol)
        else:
            return refTail
Beispiel #9
0
def amend_price(brg, orderID, newPrice):
    """
    Amend the price of an order.
    Params:
    - brg <Bargain Object>:,
    - order <str>: one existing bitmex order,
    -newPrice <int>
    """
    #    mlogger.debug(f'orderID={orderID}, newStopPx={newStopPx}, opts={opts}')
    newPrice = round_sprice(newPrice)
    try:
        order = {"orderID": orderID}  # format à vérifier pour harmonisation
        return brg.bto.amend(order, price=newPrice)
    except Exception as e:
        mlogger.exception(e)
        # le staop est probablement déjà déclenché.
        return {
            "orderID": orderID,
            "clOrdID": orderID,
            "error": "Amending error"
        }
    def retry(
        self,
        path,
        error=None,
        query=None,
        postdict=None,
        timeout=None,
        verb=None,
        rethrow_errors=False,
        max_retries=None,
        fast=False,
        exception=None,
    ):
        """Renvois la réponse du borker après un retry
        Relance l'ordre un certain nombre de fois, un après avoir attendu quelques secondes.
        Nécessite les même argurments que _curl_bitmex et dans le même ordre"""
        self.retries += 1

        if self.retries >= max_retries:
            raise ke.MaxRetries(e=exception,
                                load=postdict,
                                extra=f"{path}: Max retries hit")

        tps1 = random.uniform(1, 2)
        tps2 = random.uniform(4, 10) if self.retries > 3 else 0
        tps3 = random.uniform(20, 80) if self.retries > 6 else 0
        self.logger.warning(
            f"retry {verb} {path} {self.retries}/{max_retries}: "
            f"Pause de {round_sprice(tps1+tps2+tps3, self.symbol)} sec:"
            f' postdict={dumps(postdict or "")}')
        # going to sleep
        sleep(tps1) if fast else sleep(
            round_sprice(tps1 + tps2 + tps3, self.symbol))

        return self._curl_bitmex(path, query, postdict, timeout, verb,
                                 rethrow_errors, max_retries)
Beispiel #11
0
 def _round(x):
     """Set default symbol"""
     return round_sprice(x, symbol)
Beispiel #12
0
    def __init__(
        self,
        price,
        refPrice,
        tail_perct_init=0.5,
        head="buy",
        updatepause=6,
        timeBin=60,
        logger=None,
        max_var=2.6,
        min_flex=0.2,
        symbol="XBTUSD",
    ):
        """
        Head is the direction, need a price (market price and ref price) and
        tail_perct_init (%): default.  Le nb_enregistrement est la longeur 
        de la bd des prix 
        - Une tête sur la prix du marché référence et trois queues 
        (tails ou tails).
        - La queue bleu (Qbleue) elle suit le prix du marché toujours à la même
        distance (même épaisseur)
        - La queue rouge, c'est le stop, elle ne bouge pas tant qu'il n'y a pas 
        de bénéf.
        - La queue verte (flexTail) elle est d'épaisseur variable, 
        son prix est passé au brokeur si au dessus du refPrice
        - min_flex est le pourcentage de la refTail jusqu'ou 
        on peux réduire la flexTail ex. 80 de la ref tail
        - main_window_size c'est la taille de l'historique de ce prixObject, 
        doit être calcule en fonction de la taille de la bin voulue 
        et de la fréquence des mis à jour
        - updatepause c'est le nombre moyen de secondes entre deux mise à jour
        - timeBin c'est la taille de la fenêtre utilisé pour calculer 
        la variation de prix.
        avec la updatepause permet d'estimer la main_window_size
        - max_var en quoi? et min_flex determine la flexibilité des queue.  
        max_var est une statistique décrivant la variation nécessaire 
        pour que la queue se réduise à min_flex.  Elle est issue d'obeservation
        du marché voir getting_data.ipyng.  la var à un très long mais fine queue.
        90% < .22
        - symbol: keep track of price symbol to format and round price correctly
        """
        self.logger = get_logger(logger, sLL="INFO", name=__name__)

        self.head = head
        self.refPrice = refPrice
        self.symbol = symbol
        self.prec = PRICE_PRECISION[symbol]

        self.tail_perct_init = tail_perct_init  # tail percent sera appliqué au prix de référence nombre entre 0 et 100
        self.timeBin = timeBin
        self.updatePause = updatepause
        # essaye d'avoir un tableau plus grand que nécessaire
        # par défaut ~30
        self.main_window_size = int(timeBin / self.updatePause * 4)

        # on défini une fonction pour mettre à jour la flexTail
        # le maxiumn de variation jamais observé pour la bin en pourcentage de variation
        # TODO: mieux définir cette fonction...
        self.max_var = max_var
        N = 100
        self.neg_exps = self.__neg_exps(self.max_var, N)
        self.var_dist_hist = pd.Series(index=range(N), data=self.neg_exps)
        self.min_flex = min_flex

        # on initialise les prix et la df qui les contiendra
        # define self.data
        self.data = None
        self.data = self.__init_price_df(price, refPrice)

        # on définie l'épaisseur du stop
        self.tail_base_width = round_sprice(
            abs(self.data.refPrice.init - self.data.refTail.init), symbol)
Beispiel #13
0
    def prices(self, typeprice=None, side="buy", symbol_=None):
        """
        Show summary of current prices.

        typeprice can be 'delta', 'indexPrice', 'market', 'askPrice',

        'midPrice', 'ref_delta','market_maker', 'lastMidPrice' or None
        (for all instrument prices)
        - symbol if not user bargain symbol but maybe could want other price
        """
        _symbol = self.symbol if symbol_ is None else symbol_

        prices = {
            k: v
            for (k, v) in self.bto.instrument(_symbol).items() if "rice" in k
        }
        # prices.keys = 'maxPrice', 'prevClosePrice', 'prevPrice24h', 'highPrice',
        # 'lastPrice', 'lastPriceProtected', 'bidPrice', 'midPrice', 'askPrice',
        # 'impactBidPrice', 'impactMidPrice', 'impactAskPrice', 'markPrice',
        # 'markPrice', 'indicativeSettlePrice', 'lowPrice',
        # execInst, MarkPrice, LastPrice, IndexPrice

        ret = None
        typeprice = "" if typeprice is None else typeprice

        if typeprice == "delta":
            ret = prices["askPrice"] - prices["bidPrice"]

        elif typeprice.lower() == "indexprice":
            # S'assurer qu'il n'y a pas deux appels consécutif à moins de x seconde
            # minisytème de cache  jusquà 11s avant nouvel appel au broker
            timeLaps = now() - self.last_check_time
            msg = (f'Checking cached price'
                   f' timeLaps={timeLaps}, now={now()},'
                   f' last_check_time={self.last_check_time}'
                   f' self.cached_refPrices={self.cached_refPrices}')

            if (self.cached_refPrices is None
                    or timeLaps > Timedelta(randint(2, 11), unit="s")
                    or self.bto.dummy):
                cached_refPrices = self.get_most_recent_settlement_price()
                self.last_check_time = now()

                self.cached_refPrices = cached_refPrices
                msg += f'>>>> New Cached_refPrices={cached_refPrices} <<<<.'

            self.logger.debug(msg)

            ret = self.cached_refPrices

        elif typeprice.lower() == "lastprice":
            # askPrice > bidPrice
            ret = prices["askPrice"] if side == "buy" else prices["bidPrice"]
        elif typeprice == "market_maker":
            ret = prices["bidPrice"] if side == "buy" else prices["askPrice"]
        elif typeprice.lower() == "lastmidprice":
            ret = self.prices("midPrice")  # this is close to the last price
        elif typeprice.lower() in ["market", "market_price", "markprice"]:
            # fairePrice is the marketPrice dans XBT check markMethod
            ret = prices["markPrice"]
        elif typeprice == "ref_delta":
            ret = self.prices("midPrice") - self.prices("indexPrice")
        elif typeprice:
            ret = prices[typeprice]

        return prices if not ret else round_sprice(ret, self.symbol)