diff --git a/telegram/src/counter.py b/telegram/src/counter.py index c7b8500..8d76b7c 100644 --- a/telegram/src/counter.py +++ b/telegram/src/counter.py @@ -1,29 +1,50 @@ +from src.db_requests.offers import Offer + + def Counter(data: list): + """ + Поиск релазиован с помощью алгоритма поиска наибольшего пути + в ациклическом графе. Для этого нам нужно транспонировать исходный граф, + а потом, с помощью методом динамического программирования, найти наиболее + большой путь. Мы не будем явно транспонировать граф, мы изначально его зададим + в транспонированном виде. + """ + N = 71 INF = 100000000 + _fiat = {"RUB", "USD", "EUR", "CNY", "GBP"} + _crypto = {"USDT": 1, "BTC": 2, "BUSD": 3, "BNB": 4, "ETH": 5} + _market = {"binance": 1, "bybit": 2, "huobi": 3} + _deC = {1: "USDT", 2: "BTC", 3: "BUSD", 4: "BNB", 5: "ETH"} + _deM = {1: "binance", 2: "bybit", 3: "huobi"} + + class Coin: + def __init__(self, type, name : str): + self.type_of_coin = type + self.name = name + class LiteOffer: + """ + Оффер, подобный классу Offer.py, являющийся сжатой его версией. + Нужен для того, чтобы нормально инициализировать офферы в нашем графе. + """ + def __init__(self, big_offer): - self.receive_coin = big_offer.receive_coin - self.init_coin = big_offer.init_coin + self.receive_coin = str(big_offer.receive_coin) + self.init_coin = str(big_offer.init_coin) self.market = big_offer.market self.payment = big_offer.payment self.sell_buy = big_offer.sell_buy - self.price = float(big_offer.price) + self.price = big_offer.price self.maker_commission = big_offer.maker_commission self.taker_commission = big_offer.taker_commission - _fiat = {"RUB", "USD", "EUR", "CNY", "GBP"} - _crypto = {"USDT": 1, "BTC": 2, "BUSD": 3, "BNB": 4, "ETH": 5} - _market = {"binance": 1, "bybit": 2, "huobi": 3} - _deC = {1: "USDT", 2: "BTC", 3: "BUSD", 4: "BNB", 5: "ETH"} - _deM = {1: "binance", 2: "bybit", 3: "huobi"} - - def PosByOffer(offer: LiteOffer, type_of_offer: str): - offer_name = offer.receive_coin if type_of_offer == "receive" else offer.init_coin - if offer_name.upper() in _fiat: - return N - 1 if type_of_offer == "init" else 0 - return _crypto[offer_name] * 10 + _market[offer.market] + def PosByOffer(self, type_of_offer): + offer_name = str(self.receive_coin) if type_of_offer == "receive" else str(self.init_coin) + if offer_name.upper() in _fiat: + return N - 1 if type_of_offer == "init" else 0 + return _crypto[offer_name] * 10 + _market[self.market] def Commission(offer_name): # комса указана в рублях @@ -34,24 +55,20 @@ def Commission(offer_name): else: return 0 - """ - Поиск релазиован с помощью алгоритма поиска наибольшего пути - в ациклическом графе. Для этого нам нужно транспонировать исходный граф, - а потом, с помощью методом динамического программирования, найти наиболее - большой путь. Мы не будем явно транспонировать граф, мы изначально его зададим - в транспонированном виде. - """ if len(data) == 0: return "Invalid input" + gr = [[] for i in range(N)] for offer in data: - lite_offer = LiteOffer(offer) - if lite_offer.receive_coin.upper() in _fiat: - gr[0].append(lite_offer) - elif lite_offer.receive_coin in _crypto.keys(): - gr[PosByOffer(lite_offer, "receive")].append(lite_offer) + edge_offer = LiteOffer(offer) + pos_to = edge_offer.PosByOffer("receive") + if edge_offer.receive_coin.upper() in _fiat: + gr[0].append(edge_offer) if edge_offer.sell_buy else gr[pos_to].append(edge_offer) + elif edge_offer.receive_coin in _crypto.keys(): + gr[pos_to].append(edge_offer) if edge_offer.sell_buy else gr[0].append(edge_offer) else: - print(lite_offer.init_coin, lite_offer.receive_coin, lite_offer.market, "<-INVALID COIN", offer.id) + print(edge_offer.init_coin, edge_offer.receive_coin, edge_offer.market, "<-INVALID COIN", + offer.id) for i in range(1, len(_crypto) + 1): for j in range(2, len(_market) + 1): for k in range(1, j): @@ -64,27 +81,29 @@ def Commission(offer_name): offer_between_markets_2 = LiteOffer(modificate_offer) gr[i * 10 + k].append(offer_between_markets_2) # здесь в поле маркет указано, куда мы переводим монеты - prev = [None for i in range(N)] + prev = [LiteOffer(Offer()) for i in range(N)] dp = [-INF for i in range(N)] dp[0] = 0 def dfs(v: int, p: int): for u in gr[v]: - pos = PosByOffer(u, "init") + pos = u.PosByOffer("init") cur_commission = (min(u.taker_commission, u.maker_commission)) / 100 if u.receive_coin in _crypto.keys(): - if dp[pos] == -INF: - dp[pos] = dp[v] + u.price - u.price * cur_commission - prev[pos] = u - elif dp[v] + u.price < dp[pos]: + if dp[pos] == -INF or dp[v] + u.price < dp[pos]: dp[pos] = dp[v] + u.price - u.price * cur_commission - prev[pos] = u - if p // 10 == v // 10: - prev[pos].market = _deM[p % 10] + prev[pos] = LiteOffer(u) + # if pos == N-1: + # print(u.receive_coin, u.init_coin, "in dfs") + if pos // 10 == v // 10: + print("im here") + prev[pos].market = _deM[v % 10] + ","+_deM[pos%10] else: if u.price - dp[v] > dp[pos]: dp[pos] = u.price - dp[v] - u.price * cur_commission - prev[pos] = u + prev[pos] = LiteOffer(u) + # if pos == N-1: + # print(u.receive_coin, u.init_coin, "in dfs") if p // 10 != v // 10 or v // 10 != pos // 10: dfs(pos, v) @@ -92,19 +111,20 @@ def dfs(v: int, p: int): dfs(0, -1) ans = str() pos = N - 1 - for i in range(3): - try: - cur_offer = prev[pos] - if cur_offer.init_coin != cur_offer.receive_coin: - ans += "Buy " if cur_offer.sell_buy else "Sell " - ans += "Taker " if cur_offer.maker_commission > cur_offer.taker_commission else "Maker " - ans += cur_offer.market + " " + cur_offer.init_coin + " " + cur_offer.receive_coin + " " - ans += cur_offer.payment + " -> " - else: - ans += cur_offer.init_coin + " Transfer to next market -> " - pos = PosByOffer(cur_offer, "receive") - except Exception: - break + step = 0 + print("____________") + while pos != 0 and step < 4: + step += 1 + cur_offer = prev[pos] + if cur_offer.init_coin != cur_offer.receive_coin: + ans += "Buy " if cur_offer.sell_buy else "Sell " + ans += "Taker " if cur_offer.maker_commission > cur_offer.taker_commission else "Maker " + ans += cur_offer.market + " " + cur_offer.init_coin + " " + cur_offer.receive_coin + " " + ans += cur_offer.payment + " -> " + else: + print(cur_offer.init_coin, cur_offer.receive_coin, cur_offer.market, pos) + ans += cur_offer.init_coin + " Transfer to next market -> " + pos = cur_offer.PosByOffer("receive") if dp[N - 1] >= 0: ans += "PROFITABLY!" else: