shamhi / HamsterKombatBot

Bot that mines coins in HamsterKombat
Apache License 2.0
781 stars 235 forks source link

[Предложения] Логика автопокупки карт. Круто улучшения купил #142

Closed yacody closed 1 month ago

yacody commented 4 months ago

расчеты по закупам конечно неебически работают. въебать 25 лямов ради прибыли +10к это сильно image image

ButCheR-PRO commented 4 months ago

Та же ерунда. Это из-за новой карты в Specials (Hamster+TON=Success), которая уже на 1 лвл стоит 1М. Хорошо хоть минимальный баланс засэйвил в конфиге, так бы всё под ноль ушло.

XPacL commented 4 months ago

Так теперь логика по покупке выгодных карточек не работает получается?

ButCheR-PRO commented 4 months ago

Так теперь логика по покупке выгодных карточек не работает получается?

Там логика такая: Профит (доход в час) / цену добавляет в очередь, а потом сортирует в очереди.

                                price = upgrade['price']
                                profit = upgrade['profitPerHourDelta']
                                significance = profit / price if price > 0 else 0

                                queue.sort(key=operator.itemgetter(1), reverse=True)

Однако, этот код надо доработать.

Во первых надо уточненить значимости. Поскольку некоторые карты могут иметь нулевую цену, то следует учесть это при расчете значимости. Если цена равна нулю, значимость также должна быть нулевой. Вместо significance = profit / price if price > 0 else 0 для избегания деления на ноль, можно использовать: significance = profit / max(price, 1)

Так же, предлагаю учитывать уровень карты. Уровень карты также влияет на её прибыль. Поэтому лучше учесть уровень карты в расчете значимости, чтобы более точно определить, какая карта является наиболее прибыльной. Например, можно умножить значимость на коэффициент, зависящий от уровня карты (например, 1.1 для уровня 2, 1.2 для уровня 3 и т. д.).

    significance *= 1.1 ** level    

Так же, не помешает оптимизация сортировки. Вместо сортировки списка queue queue.sort(key=operator.itemgetter(1), reverse=True) каждый раз после добавления карты, можно использовать приоритетную очередь (heap), чтобы автоматически поддерживать список в отсортированном порядке.

queue = []
heapq.heappush(queue, (-significance, upgrade_id, upgrade))
top_cards = heapq.nsmallest(10, queue)

Так же, карточки с нулевым доходом можно не покупать автоматически, они обычно стоят от 1М, для новичков это вообще смертельно. Поэтому можно дополнительное условие сделать if tempBalance > price and level <= settings.MAX_LEVEL and profit > 0:

VintaGist commented 4 months ago

например, 1.1 для уровня 2, 1.2 для уровня 3 и т. д.

Несогласен. Текущая оценка покупки, зависящая от уровня дохода в отношении затрат на покупку, по моему мнению является более успешной. Ведь покупка одной карточки условно первого уровня с бОльшим доходом за каждую потраченную монету в долгосроке является приоритетней покупки карты условно 10го левела но с меньшим доходом за каждую потраченную монету.

Так же, карточки с нулевым доходом можно не покупать автоматически, они обычно стоят от 1М, для новичков это вообще смертельно

Да, тут есть проблема. Безусловно, покупки карточек без доходов автоматизировать не нужно и у себя предложенный код ( ... and profit > 0) я установил сразу как заметил такую покупку.

Далее, считаю что покупка карточек с высокой стоимостью должна зависеть от "прокачанности" акка. Например от дохода в час.

Условно говоря - разрешать покупки карточек, стоимость которых не превышает указанного в конфиге левела и стоимости, равному [ Одному | Двум | Трем ] часам дохода.

Готов подискутировать на данную тематику

ic23 commented 4 months ago

Не знаю, но может ещё как-то вот так делать?

earn = upgrade['currentProfitPerHour']
profit = upgrade['profitPerHourDelta']

significance = (earn + profit) / price

Сейчас постараюсь объяснить, в логике автозакупки берётся не доход в час от карточки, а насколько карточка увеличит свой доход в час. Поэтому, мне кажется что всё же лучше по окончательному доходу считать значимость, чем по тому, насколько оно увеличит.

VintaGist commented 4 months ago

significance = (earn + profit) / price

Такой формулой мы сильно преувеличиваем доходность. Проверь просто в Excel`е (я свои догадки подтвердил именно так). Выберутся карточки с бОльшим уровнем дохода в абсолютном выражении.

ButCheR-PRO commented 4 months ago

Такой формулой мы сильно преувеличиваем доходность. Проверь просто в Excel`е (я свои догадки подтвердил именно так). Выберутся карточки с бОльшим уровнем дохода в абсолютном выражении.

Согласен, но при расчётах могут быть нюансы. Давай вместе попробуем вывести идеальную формулу. Возьмем к примеру из раздела PR&Team карточку Consensus Explorer pass. На 1 lvl её цена = 25000, а доход в час = 1500. Её окупаемость составит 25000/1500=16,6 часов. На 11 lvl она уже приносит 23670 в час. Чтобы её улучшить до 12 lvl, нужно потрать 1070000 и она будет приносить уже 26830 в час, что на 23670-26830=3150 больше чем на 11 lvl. И окупаемость этого улучшения составит 1070000/26830=39,8 часов. На 12 lvl её доход в час = 26830. Цена улучшения до 13 lvl = 2010000 и она будет приносить уже 26830+3370=30200 в час, что на 3370 больше чем на 12 lvl. И окупаемость этого улучшения составит 2010000/30200=66,5 часов.

То есть мы должны учитывать окупаемость с учётом профита на следующем уровне улучшения, за который мы заплатим, а не на текущем. Для этого нам нужно вывести формулу по которой расчитываются цены следующего улучшения и профита карточек.

VintaGist commented 4 months ago

И окупаемость этого улучшения составит 2010000/30200=66,5 часов

Учитывать окупаемость в очереди возможно тоже стоит, но не думаю что так. По такой методике стоимость +3370 дохода будет составлять 2 010 000 монет. Но считаю что покупать такое улучшение резонно если нет условных 1-5 карточек, которые в сумме дадут +3370 и затрачено на них будет менее чем 2 010 000 монет. А именно этот алгоритм сейчас и есть. Он формирует очередь (корзину карточек) в порядке убывания стоимости одной единицы дохода и выкупает сверху вниз.

Для этого нам нужно вывести формулу по которой расчитываются цены следующего улучшения и профита карточек.

Как я понимаю - каждый новый уровень сильно удорожает стоимость 1 единицы дохода: Consensus Explorer pass 11lvl -> 12lvl стоит 1 070 000 за +3150 дохода (~339 монет за единицу дохода) Consensus Explorer pass 12lvl -> 13lvl стоит 2 010 000 за +3370 дохода (~596 монет за единицу дохода)

Поэтому считаю что если уже у нас есть 11lvl, 12lvl стоит покупать ПОСЛЕ покупки более дешевых единиц дохода, а именно так сейчас и есть.

Возможно я не уловил ход мысли, поясни пж.

Более актуально сейчас привязка к уровню акка. Т.к вручную новый акк прокачиваю выше, тратя экономно, чем отдав на обработку боту.

В который раз себя убеждаю что стоит привязываться к уровню дохода при покупке. Подумаю еще

ButCheR-PRO commented 4 months ago

Более актуально сейчас привязка к уровню акка. Т.к вручную новый акк прокачиваю выше, тратя экономно, чем отдав на обработку боту.

Тогда предлагаю ввести ограничение на максимальную цену апгрейда карточки. Например сейчас стоит MAX_LEVEL=12 Но в разде Specials есть карточки, типа TON+Hamster Kombat=Success, которая на 11 lvl уже стоит 42 810 000 (как и произошло в сабже)! Поэтому нужно добавить параметр в конфиге на MAX_UPGRADE_PRICE=1000000 чтобы карточки дороже чем 1 миллион оно не улучшало, даже если они меньше чем MAX_LEVEL и BALANCE_TO_SAVE позволяет её купить. в bot/config/config.py например после 16 сроки добавим: MAX_UPGRADE_PRICE: int = 1000000 Вносим коррективы в код bot/core/tapper.py (у меня 395 строка):

                                tempBalance = balance - settings.BALANCE_TO_SAVE
                                maxPrice = settings.MAX_UPGRADE_PRICE
                                if tempBalance > price and level <= settings.MAX_LEVEL and profit > 0 and price < maxPrice:

и в файле .env добавим: MAX_UPGRADE_PRICE=ВАШЕ_ЧИСЛО

shamhi commented 4 months ago

И так, подводя итоги, что нужно добавить:

В настройки:

В логику:

  1. Заменить условие на покупку:

    if tempBalance > price and level <= settings.MAX_LEVEL and profit > 0:
  2. Заменить сортировку:

    queue = []
    heapq.heappush(queue, (-significance, upgrade_id, upgrade))
    top_cards = heapq.nsmallest(10, queue)
  3. Заменить вычисление выручки:

    significance = profit / max(price, 1) 

На этом все?

yacody commented 4 months ago

И так, подводя итоги, что нужно добавить:

В настройки:

  • MAX_UPGRADE_PRICE=
  • BALANCE_TO_SAVE=

В логику:

  1. Заменить условие на покупку:
if tempBalance > price and level <= settings.MAX_LEVEL and profit > 0:
  1. Заменить сортировку:
queue = []
heapq.heappush(queue, (-significance, upgrade_id, upgrade))
top_cards = heapq.nsmallest(10, queue)
  1. Заменить вычисление выручки:
significance = profit / max(price, 1) 

На этом все?

вроде всё, но было бы круто, если бы ты ещё посмотрел можно ли пофиксить вот эту штуку image она так и не прошла со временем, после 1 норм цикла, второй цикл тупо афк

VintaGist commented 4 months ago

@shamhi, подожди немного. Давай еще немного помыслим. Я вывел очередь(корзину) и в определенный момент времени я получаю это:

Cart: compliance_officer        (9  lvl) | Price: 29950       | Profit: 206         | Significance: 0.006878130217028381 
Cart: web3_academy_launch       (12 lvl) | Price: 470943      | Profit: 3157        | Significance: 0.0067035713451521735 
Cart: licence_north_america     (12 lvl) | Price: 428130      | Profit: 2021        | Significance: 0.004720528811342349 
Cart: fan_tokens                (12 lvl) | Price: 428130      | Profit: 2000        | Significance: 0.00467147828930465 

И, получается я покупаю все эти карточки. Но, compliance_officer 10го левела выгоднее!

То есть я к тому, что хорошо было бы после покупки пройтись снова в поисках карточек, возможно открылись зависимые, или улучшить нужно ту же что уже улучшили, понимаешь?

В таком случае мы плавно поднимаем акк и не тратим много монет на дорогие карточки

shamhi commented 4 months ago

она так и не прошла со временем, после 1 норм цикла, второй цикл тупо афк

а в чем проблема? не понял

shamhi commented 4 months ago

@shamhi, подожди немного. Давай еще немного помыслим. Я вывел очередь(корзину) и в определенный момент времени я получаю это:

Cart: compliance_officer        (9  lvl) | Price: 29950       | Profit: 206         | Significance: 0.006878130217028381 
Cart: web3_academy_launch       (12 lvl) | Price: 470943      | Profit: 3157        | Significance: 0.0067035713451521735 
Cart: licence_north_america     (12 lvl) | Price: 428130      | Profit: 2021        | Significance: 0.004720528811342349 
Cart: fan_tokens                (12 lvl) | Price: 428130      | Profit: 2000        | Significance: 0.00467147828930465 

И, получается я покупаю все эти карточки. Но, compliance_officer 10го левела выгоднее!

То есть я к тому, что хорошо было бы после покупки пройтись снова в поисках карточек, возможно открылись зависимые, или улучшить нужно ту же что уже улучшили, понимаешь?

В таком случае мы плавно поднимаем акк и не тратим много монет на дорогие карточки

то есть, сделать 2 круга покупок за один раз?

ButCheR-PRO commented 4 months ago
  1. Заменить условие на покупку:
if tempBalance > price and level <= settings.MAX_LEVEL and profit > 0:

Я бы заменил на:

tempBalance = balance - settings.BALANCE_TO_SAVE
maxPrice = settings.MAX_UPGRADE_PRICE
if tempBalance > price and level <= settings.MAX_LEVEL and profit > 0 and price < maxPrice:

Потом ещё на 410 строке сделать более удобный вывод, например вот так:


logger.success(
f"{self.session_name} | "
f"Successfully upgraded <e>{upgrade[0]}</e> with price <r>{upgrade[3]:,}</r> to <m>{upgrade[2]}</m> lvl | "
f"Earn every hour: <y>{earn_on_hour:,}</y> (<g>+{upgrade[4]}</g>) | "
f"Money left: <e>{balance:,}</e>")

Я бы везде заменил {earn_on_hour} и {balance} на {earn_on_hour:,} и {balance:,}
VintaGist commented 4 months ago

то есть, сделать 2 круга покупок за один раз?

Нет. Нам по сути очередь не нужна. После каждой покупки мы проверяем снова и снова весь перечень карточек и покупаем одну, самую дешевую прокачку доходности (max(significance)) пока не упремся в BALANCE_TO_SAVE или [ MAX_UPGRADE_PRICE | MAX_LEVEL ]

Такой алгоритм максимально эффективен если вводим MAX_UPGRADE_PRICE, хотя его лучше привязать к уровню прокачки акка. Пока формулы у меня нет, т.к она должна быть прогрессивной. Надо подумать

ButCheR-PRO commented 4 months ago

Пока формулы у меня нет, т.к она должна быть прогрессивной. Надо подумать

Может так: maxPrice = earn_on_hour * 5 Например у нас доход в час = 500 000, тогда maxPrice будет 500000 x 5=2 500 000. А если у нас доход в час = 50 000, то maxPrice = 50000 x 5=250000. То есть коэффициент равен сумме дохода за 5 часов.

VintaGist commented 4 months ago

Это первое что приходит в голову, но есть пару нюансов. Мы в одном условном докере запускаем 3 акка: 800к, 200к и 1к доходности. На все акки действуют одни настройки (.env). Значит по такому алгоритму: для 800к до 40кк; для 200к до 1кк; для 1к до 5к; Вроде бы и ничего, но у 1к есть 5лямов за ежедневку, я не уверен что он сможет их потратить. А 800к согласен ли будет выложить 40кк за карточку? Хз.

Может ввести коэф. зависящий от баланса? Или мы сильно усложняем схему?

В идеале бы посмотреть на таблицу прокачек карточек (уровни/стоимость). Поделить если есть у кого.

ButCheR-PRO commented 4 months ago

для 800к до 40кк;

800 000 x 5 = 4 000 000

Может ввести коэф. зависящий от баланса?

Если у меня доход в час 800к, а на балансе 100 000? А на втором аккаунте доход в час 5к, а баланс 5 000 000? Тогда нужно коэффициент брать из дохода в час + баланс. Например:

maxPrice = (earn_on_hour * 5 + balance) / 10

Тогда если у нас на одном аккаунте доход 5к в час, а баланс 5 000 000, то maxPrice = 5000x5+5000000/10=525 000 На втором аккаунте у нас доход 800к в час, а на балансе 50 000 000, тогда maxPrice = 800000x5+50000000/10=9 000 000 А если у нас доход 800к в час, а на балансе 100 000, тогда maxPrice = 800000 x 5+100000/10=4 010 000 И с повышением денег на балансе, этот лимит будет расти. И не забываем про BALANCE_TO_SAVE

VintaGist commented 4 months ago

maxPrice = earn_on_hour * 5

В любом случае это лучше чем константа MAX_UPGRADE_PRICE для нескольких акков в одном скрипте Однозначно лучше подкорректировать эти 5.

800 000 x 5 = 4 000 000

Да, верно, проверка на внимательное чтение пройдена) *Шучу, ошибся, спешил куда-то

Предлагаю так: maxPrice = earn_on_hour * 5 и стоимость единоразовой покупки не выше, например, (баланс - BALANCE_TO_SAVE)*0,7

То есть на одну покупку можем потратить не более 70% "свободных" денег

Тогда если у нас на одном аккаунте доход 5к в час, а баланс 5 000 000, то maxPrice = 5000*5+5000000/10=525000

5000*5 and (5 000 000 - 2 000 000) * 0.7 > 5000 (то есть покупаем до 2 100 000, чем меньше баланс тем больше "свободных" денег в пропорции)

ButCheR-PRO commented 4 months ago

maxPrice = earn_on_hour * 5 и стоимость единоразовой покупки не выше, например, (баланс - BALANCE_TO_SAVE)*0,7 Допустим что у нас в конфиге BALANCE_TO_SAVE=2000000

tempBalance = balance - settings.BALANCE_TO_SAVE
maxPrice =  (earn_on_hour * 5) + (tempBalance * 0.7)
if tempBalance > price and level <= settings.MAX_LEVEL and profit > 0 and price < maxPrice:

Тогда если у нас на одном аккаунте доход 5к в час, а баланс 5 000 000, то maxPrice = 5000*5+(5000000-2000000)*0.7=2 125 000 Если доход 800к в час, а на балансе 50 000 000, тогда maxPrice = 800000*5+(50000000-2000000)*0,7=37 600 000 Если доход 800к в час, а на балансе 100 000, тогда maxPrice = 800000*5+(100000-2000000)*0,7=2 670 000 Если доход 5к в час, а на балансе 100 000, тогда maxPrice = 5000*5+(100000-2000000)*0.7=-1 305 000 (но тогда не выполняется условие tempBalance > price)

VintaGist commented 4 months ago

Тогда если у нас на одном аккаунте доход 5к в час, а баланс 5 000 000, то maxPrice = 5000*5+3000000*0.7=2 125 000 Если доход 800к в час, а на балансе 50 000 000, тогда maxPrice = 800000*5+50000000*0,7=39 000 000 Если доход 800к в час, а на балансе 100 000, тогда maxPrice = 800000*5+100000*0,7=4 070 000

Немножко не так. Нам нужно не превысить 70% от "свободных денег" на одну покупку:

free_money = balance - settings.BALANCE_TO_SAVE
max_price_limit = earn_on_hour * 5
if (free_money*0.7) >= price and level <= settings.MAX_LEVEL and profit > 0 and price < max_price_limit:
ButCheR-PRO commented 4 months ago

free_money = balance - settings.BALANCE_TO_SAVE max_price_limit = earn_on_hour 5 if (free_money0.7) >= price and level <= settings.MAX_LEVEL and profit > 0 and price < max_price_limit:

Так если у нас не выполнится условие price < maxPrice то всё остальное не имеет значение. А оно может не выполниться: Если доход в час 5000, то 5000*5=25000. Поэтому карточки дороже 25000 не будут покупаться.

PS: давай не будем путать названия переменных, вместо free_money уже есть tempBalance, а вместо max_price_limit есть maxPrice. А то щас каша получится в сообщениях. На проде можно будет поменять.

VintaGist commented 4 months ago

Вроде бы и ничего, но у 1к есть 5лямов за ежедневку, я не уверен что он сможет их потратить.

Я писал об этой проблеме, но выкупая карточки до 25к мы же подымаем и доходность. Нужно тестировать.

PS: давай не будем путать названия переменных, вместо free_money уже есть tempBalance, а вместо max_price_limit есть maxPrice. А то щас каша получится в сообщениях.

Мне не принципиально, просто там в коде нет кемел-кейса. Да и практика заставляет не использовать temp... и прочего типа названия для переменных. Только осмысленные значения. Это сейчас не так важно. Давай про суть

ButCheR-PRO commented 4 months ago

Давай про суть

Если BALANCE_TO_SAVE=2000000 то когда на балансе меньше 2 000 000, автоапгрейд не работает. Поэтому баланс менее 2 000 000 не рассматриваем. Далее возьмём эту формулу: maxPrice = (earn_on_hour * 5) + (tempBalance * 0.7) Тогда смоделируем ситуации и подставим формулу:

earn_on_hour: 5 000 | Balance: 5 000 000 | maxPrice: 2 125 000 
earn_on_hour: 800 000 | Balance: 50 000 000 | maxPrice: 37 600 000
earn_on_hour: 800 000 | Balance: 3 000 000 | maxPrice: 4 700 000
earn_on_hour: 5 000 | Balance: 2 500 000 | maxPrice: 375 000

BALANCE_TO_SAVE тоже можно сделать динамическим, по формуле, но оставить возможность ручного ограничения в конфиге (два условия для проверки). Потому как maxPrice: 37 600 000, я всё равно не считаю целесообразным тратить на улучшение более 8 000 000. В .env задать MAX_UPGRADE_PRICE=8000000 и

                                tempBalance = balance - settings.BALANCE_TO_SAVE
                                maxPrice =  (earn_on_hour * 5) + (tempBalance * 0.7)
                                if tempBalance > price and level <= settings.MAX_LEVEL and profit > 0 and price < maxPrice and price < settings.MAX_UPGRADE_PRICE:

Тогда можно безопасно задавать в конфиге MAX_LEVEL=20

VintaGist commented 4 months ago

maxPrice = (earn_on_hour 5) + (tempBalance 0.7)

Я не понимаю смысла в этой формуле. Поясни. Ты же сам предлагаешь такой расчет: earn_on_hour: 800 000 | Balance: 3 000 000 | maxPrice: 4 700 000 Как 4,7кк соотносятся с балансом в 3кк и 2кк резерва?

Потому как maxPrice: 37 600 000, я всё равно не считаю целесообразным тратить на улучшение более 8 000 000.

Посмотри еще раз на мой вариант:

free_money = balance - settings.BALANCE_TO_SAVE
max_price_limit = earn_on_hour * 5
if (free_money*0.7) >= price and level <= settings.MAX_LEVEL and profit > 0 and price < max_price_limit:

Если подставить сюда не 0,7, а, например, 0,166 (16% от свободных денег) можно получить то, чего ты хочешь (не тратить выше 8кк при 50кк) но другой, мелкий акк, сломается)

На практике получится иначе, при 50кк баланса обычно уже очень прокачанные карточки и дешевых там просто не будет, потому лучше оставить 0.7 и подождать фидбек.

ButCheR-PRO commented 4 months ago

max_price_limit = earn_on_hour 5 if (free_money0.7) >= price and price < max_price_limit:

Хорошо, заменяем maxPrice на max_price_limit и tempBalance на free_money во избежание дальнейшей путаницы.

Но меня смущает условие. Давай посмотрим на твоё условие: if (free_money*0.7) >= price and price < max_price_limit:

Теперь возьмем earn_on_hour = 5000, balance=5000000 и BALANCE_TO_SAVE=2000000 Получаем: 5000*5=25 000, free_money*0.7=2 100 000 Если 2100000 >цена апгрейда И цена апгрейда < 25000 то: получается лимит = 25000. А если там за 100 000 есть карточка с гораздо большим профитом, то оно её не купит, а будет скупать мелочь до 25000 с меньшим профитом.

Я же предлагаю формулу и условия:

free_money = balance - settings.BALANCE_TO_SAVE
max_price_limit =  (earn_on_hour * 5) + (free_money * 0.7)
if free_money > price and level <= settings.MAX_LEVEL and profit > 0 and price < max_price_limit and price < 
 settings.MAX_UPGRADE_PRICE:

Если например MAX_UPGRADE_PRICE=8000000 то: 5000*5+3000000*0,7=25 000 + free_money*0.7=2 125 000 Если 2125000 >цена апгрейда И цена апгрейда < 8000000 то: получается лимит = 2125000. Но если у нас будет max_price_limit = 33 600 000 и карточка price= 30 000 000, то верхний порог всё равно = 8000000 и задаётся в конфиге.

На практике получится иначе, при 50кк баланса обычно уже очень прокачанные карточки и дешевых там просто не будет, потому лучше оставить 0.7 и подождать фидбек.

Если в конфиге MAX_LEVEL=20, то карточки из вкладки Markets или PR на 15 lvl будут стоить менее 1кк, а карточки из Specials уже на 5 lvl некоторые стоят более 5кк. Поэтому пусть оно лучше все дешевые карточки докачает до 20 lvl, а потом уже можно прокачать самые дорогие которые свыше 8кк стоят. Когда не останется дешевых карточек, можно вручную в конфиге повышать MAX_UPGRADE_PRICE=50000000

VintaGist commented 4 months ago

можно вручную в конфиге повышать MAX_UPGRADE_PRICE=50000000

Не будет работать для 2+ акка.

В общем я так понимаю мы не можем найти консенсус по максимальной сумме покупки.

Давай для начала упростим и опишем хотелки.

Вот мои, например:

  1. Для новых акков (доход до 300к) тратим от 90% до 70% "свободных денег" на одну покупку
  2. Для "средних" (300к - 600к) 70%-60%
  3. Для "топ" (600к-1кк) 60%-30%
  4. Для "мега" (1кк+) = 30%
ButCheR-PRO commented 4 months ago
  • Для новых акков (доход до 300к) тратим от 90% до 70% "свободных денег" на одну покупку
  • Для "средних" (300к - 600к) 70%-60%
  • Для "топ" (600к-1кк) 60%-30%
  • Для "мега" (1кк+) = 30%

У нас же ещё есть total: total = int(player_data.get('totalCoins', 0)) Может по этому значению определять коэффициент? Или банально сделать условия на сумму earn_on_hour для каждого диапазона свой фиксированный коэффициет. Но тогда даже одна копейка сможет отделять тебя от перехода в следующий диапазон (например 299к и 300к), слишком чёткие границы


# Новички
if earn_on_hour < 300000:
    min_percent = 0.7
    max_percent = 0.9
    percent = min_percent + (max_percent - min_percent) * (earn_on_hour / 300000)
    max_price_limit = (earn_on_hour * 5) + (free_money * percent)
    max_price_for_upgrade = free_money * min_percent

# Средние
elif 300000 <= earn_on_hour < 600000:
    min_percent = 0.6
    max_percent = 0.7
    percent = max_percent - (max_percent - min_percent) * ((earn_on_hour - 300000) / 300000)
    max_price_limit = (earn_on_hour * 5) + (free_money * percent)
    max_price_for_upgrade = free_money * min_percent

# Топ
elif 600000 <= earn_on_hour < 1000000:
    min_percent = 0.3
    max_percent = 0.6
    percent = max_percent - (max_percent - min_percent) * ((earn_on_hour - 600000) / 400000)
    max_price_limit = (earn_on_hour * 5) + (free_money * percent)
    max_price_for_upgrade = free_money * min_percent

# Мега
else:
    max_price_limit = (earn_on_hour * 5) + (free_money * 0.3)
    max_price_for_upgrade = free_money * 0.3

if free_money > price and level <= settings.MAX_LEVEL and profit > 0 and price < max_price_limit and price <= max_price_for_upgrade:

Я добавил новую переменную max_price_for_upgrade, которая вычисляет верхний % от свободных денег на балансе, например 70%: (free_money * 0.7). В условии if добавил новое ограничение price <= max_price_for_upgrade, которое проверяет, что цена карточки не превышает 70% от свободных денег на балансе.

Для каждого диапазона дохода в час (earn_on_hour) определены минимальный (min_percent) и максимальный (max_percent) проценты, которые необходимо использовать. Так же, внутри каждого диапазона рассчитывается процент с использованием линейной интерполяции между min_percent и max_percent на основе текущего значения earn_on_hour. Ну и max_price_limit и max_price_for_upgrade вычисляются с использованием рассчитанного процента.

Теперь процент, используемый для расчета лимитов, будет равномерно распределен в диапазоне дохода в час. Например, для новичков с доходом 1000 в час процент будет равен 0.9, а с доходом 300000 в час процент будет равен 0.7. Для средних с доходом 300000 в час процент будет 0.7, а с доходом 600000 в час процент будет 0.6.

VintaGist commented 4 months ago

слишком чёткие границы

Да, соглашусь, резковато.

Тогда давай размажем плавно на весь диапазон 0-1кк. Если 1кк = 30%, 0=90% то формула будет такой: 90 - (( 90 - 30) * earn_on_hour / 1 000 000)

В коде реализовать можно приблизительно так:

free_money = balance - settings.MIN_AVAILABLE_SUM

# не дать покупать дорогие карточки новым аккам
max_price_limit = earn_on_hour * 5 

# ограничение для дохода 1кк+ в час
max_price_for_upgrade = free_money * 0.3
# не готовы тратить выше 90% для новых акков и 30% для дохода в 1кк+/час
if earn_on_hour < 1000000:
    max_percentage_of_costs = 90 - (60 * earn_on_hour / 1000000)
    max_price_for_upgrade = free_money * max_percentage_of_costs / 100

if max_price_for_upgrade > price and level <= settings.MAX_LEVEL and profit > 0 and price < max_price_limit:
    queue.append([upgrade_id, significance, level, price, profit])

....
VintaGist commented 4 months ago

Для каждого диапазона дохода в час (earn_on_hour) определены минимальный (min_percent) и максимальный (max_percent) проценты, которые необходимо использовать. Внутри каждого диапазона рассчитывается percent с использованием линейной интерполяции между min_percent и max_percent на основе текущего значения earn_on_hour. max_price_limit и max_price_for_upgrade вычисляются с использованием рассчитанного percent.

ChatGPT? 😉

DanielCodeWeb commented 4 months ago

Можете пожалуйста поделиться готовым кодом, где прописана новая логика. Допустим архивом

ButCheR-PRO commented 4 months ago

ChatGPT? 😉

Ага, я уже в робота превращаюсь с этим кодом.

                                free_money = balance - settings.BALANCE_TO_SAVE
                                max_price_limit = earn_on_hour * 5 
                                max_price_for_upgrade = free_money * 0.3

                                if earn_on_hour < 1000000:
                                    max_percentage_of_costs = 90 - (60 * earn_on_hour / 1000000)
                                    max_price_for_upgrade = free_money * max_percentage_of_costs / 100

                                if max_price_for_upgrade > price and level <= settings.MAX_LEVEL and profit > 0 and price < max_price_limit and price <= settings.MAX_UPGRADE_PRICE:
                                    queue.append([upgrade_id, significance, level, price, profit])

Давай проверим что получается:

earn_on_hour: 1 100 000 | Balance: 50 000 000 | max_price_for_upgrade: 14 400 000 # но по факту 5.5кк лимит из-за max_price_limit 
earn_on_hour: 1 100 000 | Balance: 5 000 000 | max_price_for_upgrade: 900 000 # но по факту 5.5кк лимит из-за max_price_limit 
earn_on_hour: 800 000 | Balance: 50 000 000 | max_price_for_upgrade: 20 160 000 # но по факту 4кк лимит из-за max_price_limit 
earn_on_hour: 800 000 | Balance: 3 000 000 | max_price_for_upgrade: 480 000 # но по факту 4кк лимит из-за max_price_limit 
earn_on_hour: 5 000 | Balance: 2 500 000 | max_price_for_upgrade: 448 500 # но по факту 25000 лимит из-за max_price_limit 
earn_on_hour: 5 000 | Balance: 5 000 000 | max_price_for_upgrade: 2 691 000 # но по факту 25000 лимит из-за max_price_limit 
earn_on_hour: 5 000 | Balance: 100 000 | max_price_for_upgrade: -1704300 # но по факту 25000 лимит из-за max_price_limit 
earn_on_hour: 25 000 | Balance: 30 000 000 | max_price_for_upgrade: 24 780 000 # но по факту 125000 лимит из-за max_price_limit 
ButCheR-PRO commented 4 months ago

Можете пожалуйста поделиться готовым кодом, где прописана новая логика. Допустим архивом

bot.zip

Вот прикрепил архив с изменёнными файлами. Ну а в .env строчки

BALANCE_TO_SAVE=2000000
MAX_UPGRADE_PRICE=10000000

добавите самостоятельно

yacody commented 4 months ago

она так и не прошла со временем, после 1 норм цикла, второй цикл тупо афк

а в чем проблема? не понял

ну он фармит всю энергию, ждет время из конфига, простот забирает пассивный заработок и опять уходит в сон на время из конфига, хотя должен начать повторно фармить

mesteruh commented 4 months ago

Можете пожалуйста поделиться готовым кодом, где прописана новая логика. Допустим архивом

bot.zip

Вот прикрепил архив с изменёнными файлами. Ну а в .env строчки

BALANCE_TO_SAVE=2000000
MAX_UPGRADE_PRICE=10000000

добавите самостоятельно

мб создашь pr ?

VintaGist commented 4 months ago

мб создашь pr ?

Тут всем резко стало некогда 😀

@shamhi, поправишь? PR смогу сделать где-то с понедельника-вторника уже.

mesteruh commented 4 months ago

мб создашь pr ?

Тут всем резко стало некогда 😀

@shamhi, поправишь? PR смогу сделать где-то с понедельника-вторника уже.

тут есть ещё один pr в процессе ревью. там тоже есть какая то хитрая логика покупки. Плюс исправлено много косяков

VintaGist commented 4 months ago

Итого по текущему разговору ( для @shamhi ):

  1. Самое сложное и самое важное: плавная прокачка акка не тратя большие суммы на дорогие карточки, если они не выгодны

  2. Вводим минимальный лимит затрат BALANCE_TO_SAVE и используем в закупке

    for upgrade in queue:
        if balance > settings.BALANCE_TO_SAVE and (balance - settings.BALANCE_TO_SAVE) > upgrade[3] and upgrade[2] <= settings.MAX_LEVEL:
  3. Ограничиваем покупку максимальным значением в 70% "свободных денег"

    free_money = balance - settings.BALANCE_TO_SAVE
    max_price_limit = earn_on_hour * 5
    if (free_money * 0.7) >= price and level <= settings.MAX_LEVEL and profit > 0 and price < max_price_limit:

4 Не покупаем карточки, которые не приносят доход and profit > 0

    if (free_money * 0.7) >= price and level <= settings.MAX_LEVEL and profit > 0 and price < max_price_limit:
  1. Добавляем сумму покупки и баланс в лог

     logger.success(
        f"{self.session_name} | "
            f"Successfully upgraded <e>{upgrade[0]}</e> with price <r>{upgrade[3]:,}</r> to <m>{upgrade[2]}</m> lvl | "
            f"Earn every hour: <y>{earn_on_hour:,}</y> (<g>+{upgrade[4]}</g>) | "
            f"Money left: <e>{balance:,}</e>")

    в вызовах logger.info() и logger.success() заменить вывод {earn_on_hour} и {balance} на {earn_on_hour:,} и {balance:,}

  2. Заменить вычисление выручки (бесплатную карточку выкупим первой, если есть доход по ней) :

    significance = profit / max(price, 1) 
  3. Заменить сортировку (по необходимости, при решении п.1 - нужно изменить):

    queue = []
    heapq.heappush(queue, (-significance, upgrade_id, upgrade))
    top_cards = heapq.nsmallest(10, queue)
VintaGist commented 4 months ago

тут есть ещё один pr в процессе ревью. там тоже есть какая то хитрая логика покупки. Плюс исправлено много косяков

Смарт в п.1, см выше

VintaGist commented 4 months ago

Я для себя добавил еще вывод корзины в консоль, рандомную спячку при закупке (randint(2, 5)), рандомную спячку при отсутствии энергии:

 if available_energy < settings.MIN_AVAILABLE_ENERGY:

    random_sleep = randint(settings.SLEEP_BY_MIN_ENERGY-300, settings.SLEEP_BY_MIN_ENERGY+100)
    logger.info(f"{self.session_name} | Minimum energy reached: {available_energy}")
    logger.info(f"{self.session_name} | Sleep {random_sleep}s")

    await asyncio.sleep(delay=random_sleep)

Естественно SLEEP_BY_MIN_ENERGY должен быть более 350, у меня 600. Без такой проверки код в продакшн не подходит, конечно. Просто даю для идеи

mesteruh commented 4 months ago

Внёс pr. Можете пока у меня с репы качать, пока в основную не попал.

ps Файлы взял у @ButCheR-PRO @VintaGist если что забыл - укажи

VintaGist commented 4 months ago

@VintaGist если что забыл - укажи

Указываю, ты не поправил .env-example

mesteruh commented 4 months ago

@VintaGist если что забыл - укажи

Указываю, ты не поправил .env-example

в readme что писать | BALANCE_TO_SAVE | минимальный лимит затрат | MAX_UPGRADE_PRICE | макс цена апгрейда

VintaGist commented 4 months ago

в readme что писать | BALANCE_TO_SAVE | минимальный лимит затрат | MAX_UPGRADE_PRICE | макс цена апгрейда

Посмотри по tapper.py. У меня иные настройки

ButCheR-PRO commented 4 months ago

Я для себя добавил еще вывод корзины в консоль,

Так скинь свой код корзины. Отображение корзины (очереди покупок) в консоле так же можно переключать из конфига, например QUEUE_LOG=True Думаю будет многим полезно для проверки и отладки.

BALANCE_TO_SAVE | минимальный лимит затрат

Это скорее минимальный баланс или НЗ (Неприкосновенный запас), который не будет тратиться на автопокупку карточек. Только сумма свыше этого баланса будет расходоваться по логике бота. И эта сумма уже будет называться free_money (свобдные деньги).

VintaGist commented 4 months ago

Так скинь свой код корзины. Отображение корзины (очереди покупок) в консоле так же можно переключать из конфига, например QUEUE_LOG=True Думаю будет многим полезно для проверки и отладки

                            for upgrade in queue:
                                logger.info(
                                    f"{self.session_name} |"
                                    f" Cart: <e>{upgrade[0].ljust(25)}</e> ({str(upgrade[2]).ljust(3)}lvl) |"
                                    f" Price: {str(upgrade[3]).ljust(11)} |"
                                    f" Profit: {str(upgrade[4]).ljust(11)} |"
                                    f" Order: {upgrade[1]} ")  
UNLUCKYxx commented 4 months ago

можно пожалуйста итоговый результат

RRR795 commented 4 months ago

А случаем не было ли идеи реализовать бота, запуская игру в браузере? Я запускал ее в web версии и брал некую ссылку (рядом с iframe) из кода элемента, видимо с токеном, там менял weba на android и так запускал некоторые кликеры, в том числе и хомяка. Или через телеграммные библиотеки рациональнее? Плохо шарю в программировании впринципе, была идея написать что-то методом ctrl+c на библиотеке selenium

yacody commented 4 months ago

А случаем не было ли идеи реализовать бота, запуская игру в браузере? Я запускал ее в web версии и брал некую ссылку (рядом с iframe) из кода элемента, видимо с токеном, там менял weba на android и так запускал некоторые кликеры, в том числе и хомяка. Или через телеграммные библиотеки рациональнее? Плохо шарю в программировании впринципе, была идея написать что-то методом ctrl+c на библиотеке selenium

смысл от этого? будет тоже самое, только у тебя будет окно браузера всегда открыто разве что код фул переписывать, делая имитацию кликов