Перейти к публикации
Форум ботоводов

admin

Administrators
  • Публикации

    55
  • Зарегистрирован

  • Посещение

  • Дней в лидерах

    9

Последний раз admin выиграл 4 февраля

Публикации admin были самыми популярными!

Репутация

22 Excellent

5 подписчиков

Посетители профиля

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

  1. admin

    Свечи в боте

    Читать документацию, официальную или переведенную, иначе никак В данном случае данные расположены так [ [ 1499040000000, // Время открытия "0.01634790", // Цена открытия (Open) "0.80000000", // Максимальная цена (High) "0.01575800", // Минимальная цена (Low) "0.01577100", // Цена закрытия (Close) "148976.11427815", // Объем 1499644799999, // Время закрытия "2434.19055334", // Объем квотируемой валюты 308, // Кол-во сделок "1756.87402397", // Taker buy base asset volume "28.46694368", // Taker buy quote asset volume "17928899.62484339" // Ignore ] ]
  2. admin

    Свечи в боте

    Свеча устроена так: Нижняя точка - минимальная цена за период, высшая - максимальная цена Если цена закрытия свечи выше цены открытия, то верхняя горизонтальная линия - цена закрытия, нижняя - цена открытия. Такие свечи обычно рисуют зеленым. Если цена закрытия свечи ниже (цена упала), то верхняя горизонтальная линия - цена открытия, нижняя - цена закрытия. Такие свечи обычно рисуют красным. Соответственно, что бы найти молот, для свечи должны быть справедливы условия: high > low close > open # цена подросла open > (high+low)/2 # цена открытия выше, чем середина "палки" close < high # сверху виднеется кусок "палки" Собственно всё. Дальше можно под себя подстраивать, например что бы низ тела свечи был выше, чем, скажем, 70% от тени, тело свечи занимало минимум 8% от тени (высота зеленой области к общей высоте и т.п.), это обычные вычисления.
  3. Вы не тот метод берете, вы берете depth - фактически стакан А нужно брать klines - свечи за период, и функции на вход давать массив из close значений Тогда она отработает и вернет текущий индекс RSI, если правильно написана В талиб тоже самое, real = talib.RSI(close, timeperiod=14) Как для MACD считаете те же значения, не думаю, что тут нужна функция если уже используется ta-lib
  4. Ну вообще да, отправили запрос, посмотрели код ответа, если 429, то нужно притормозить.. Вот примерно так можно подойти к опасной черте, если интернет хороший, и отойти назад import requests while True: # В бесконечном цикле получаем тикер без пауз и без пар, пока не погонят r = requests.get('https://api.binance.com/api/v1/ticker/24hr') print("Код ответа Binance", r.status_code) # r.status_code = 200 => Всё ок, ответ получен без проблем # r.status_code = 429 => Превышен лимит, пора сделать паузу # r.status_code = 418 => Всё, забанили на пару минут, если продолжать то время бана увеличится if r.status_code != 200: break А вообще всё зависит от архитектуры программы, может быть if else, может быть есть смысл вызывать исключение, которое будет перехвачено где-то в коде, зависит от ситуации
  5. Это можно делать с любым из них, даже есть готовая инструкция 🙂 https://bablofil.ru/kak-zapustit-bota-na-servere/
  6. admin

    Арбитраж

    Биржи с этим сражаются, устанавливая высокие комиссии за ввод и вывод средств. Что касается крипты, то перевод денег с одной биржи на другую занимает приличное время, за это время курсы меняются. Тут лучше сработает подход, где средства закинуты на биржи, они делятся пополам, зеркально закупаются и потом зеркально продаются при удобном случае. Но тут вступает фактор того, что на биржах с большими объемами уже множество ботов, которые это делают и мешают друг-другу, а на мелких не те объемы и не так часто меняются курсы. В общем, жизнь вносит свои коррективы.
  7. Всё упирается в то, как заранее узнать пик это или еще нет? И если падение, то будет ли взлет. И как понять, что падение закончилось? Есть множество подходов к определению этих моментов, 100% достоверных вроде как нет То, что вы описали, это идеальпре поведение для любого бота.
  8. Обновил код, посмотрите
  9. Добрый день! Для биттрекса нужно немного изменить код, вот так: import numpy import talib import requests import json import time from matplotlib.finance import candlestick2_ohlc import matplotlib.animation as animation import matplotlib.pyplot as plt import matplotlib.ticker as ticker from datetime import datetime BEAR_PERC = 70 BULL_PERC = 30 PAIR = 'USD-BTC' fig, ax = plt.subplots(3, sharex=True) fig.comment = plt.figtext(.7,.05, '') def update_graph(interval): try: data = requests.get("https://international.bittrex.com/Api/v2.0/pub/market/GetTicks?_=1500915289433&marketName={pair}&tickInterval=fiveMin".format(pair=PAIR)).json()['result'][-200:] quotes = {} quotes['open']=numpy.asarray([item['O'] for item in data]) quotes['close']=numpy.asarray([item['C'] for item in data]) quotes['high']=numpy.asarray([item['H'] for item in data]) quotes['low']=numpy.asarray([item['L'] for item in data]) xdate=[datetime.strptime(item['T'], '%Y-%m-%dT%H:%M:%S') for item in data] ax[0].xaxis.set_major_locator(ticker.MaxNLocator(6)) def chart_date(x,pos): try: return xdate[int(x)] except IndexError: return '' ax[0].clear() ax[0].xaxis.set_major_formatter(ticker.FuncFormatter(chart_date)) candlestick2_ohlc(ax[0], quotes['open'],quotes['high'],quotes['low'],quotes['close'],width=0.6) # print(ax[0].get_xdata()) fig.autofmt_xdate() fig.tight_layout() macd, macdsignal, macdhist = talib.MACD(quotes['close'], fastperiod=12, slowperiod=26, signalperiod=9) ax[1].clear() ax[1].plot(macd, color="y") ax[1].plot(macdsignal) idx = numpy.argwhere(numpy.diff(numpy.sign(macd - macdsignal)) != 0).reshape(-1) + 0 inters = [] for offset, elem in enumerate(macd): if offset in idx: inters.append(elem) else: inters.append(numpy.nan) ax[1].plot(inters, 'ro') #ax[1].scatter(x=ax[0].get_xdata(), y=inters, c='b') hist_data = [] max_v = 0 for offset, elem in enumerate(macdhist): activity_time = False curr_v = macd[offset] - macdsignal[offset] if abs(curr_v) > abs(max_v): max_v = curr_v perc = curr_v/max_v if ( (macd[offset] > macdsignal[offset] and perc*100 > BULL_PERC) # восходящий тренд or ( macd[offset] < macdsignal[offset] and perc*100 < (100-BEAR_PERC) ) ): v = 1 activity_time = True else: v = 0 if offset in idx and not numpy.isnan(elem): # тренд изменился max_v = curr_v = 0 # обнуляем пик спреда между линиями hist_data.append(v*1000) ax[2].clear() ax[2].fill_between([x for x in range(len(macdhist))], 0, hist_data, facecolor='green', interpolate=True) plt.gcf().texts.remove(fig.comment) fig.comment = plt.figtext(.7,.05, '%s %s%s' % (PAIR, time.ctime(), ' ТОРГУЕМ!!!! ' if activity_time else ''), style='italic', bbox={'facecolor':'red' if activity_time else 'green', 'alpha':0.5, 'pad':10}) except: pass ani = animation.FuncAnimation(fig, update_graph, interval=1000) plt.show() и всё получится
  10. У вас всё есть уже, вам надо просто совместить два скрипта, вот как то так, приложил это еще и в файлах import sqlite3 import logging import time import os import math from datetime import datetime from binance_api import Binance bot = Binance( API_KEY='', API_SECRET='' ) def process_trailing(settings): multiplier = -1 if settings['strategy'] == "Long" else 1 print("Получаем настройки пар с биржи") symbols = bot.exchangeInfo()['symbols'] step_sizes = {symbol['symbol']:symbol for symbol in symbols} for symbol in symbols: for f in symbol['filters']: if f['filterType'] == 'LOT_SIZE': step_sizes[symbol['symbol']] = float(f['stepSize']) while True: try: print('Проверяю пару {pair}, стратегия {strategy}'.format(pair=settings['symbol'], strategy=settings['strategy'])) # Получаем текущие курсы по паре current_rates = bot.depth(symbol=settings['symbol'], limit=5) bid=float(current_rates['bids'][0][0]) ask=float(current_rates['asks'][0][0]) # Если играем на повышение, то ориентируемся на цены, по которым продают, иначе на цены, по которым покупают curr_rate = bid if settings['strategy'] == "Long" else ask if settings['stop_loss_fixed'] == 0: settings['stop_loss_fixed'] = (curr_rate/100) * (settings['stop_loss_perc']*multiplier+100) print("Текущие курсы bid {bid:0.8f}, ask {ask:0.8f}, выбрана {cr:0.8f} stop_loss {sl:0.8f}".format( bid=bid, ask=ask, cr=curr_rate, sl=settings['stop_loss_fixed'] )) # Считаем, каким был бы stop-loss, если применить к нему % curr_rate_applied = (curr_rate/100) * (settings['stop_loss_perc']*multiplier+100) if settings['strategy'] == "Long": # Выбрана стратегия Long, пытаемся продать монеты как можно выгоднее if curr_rate > settings['stop_loss_fixed']: print("Текущая цена выше цены Stop-Loss") if curr_rate_applied > settings['stop_loss_fixed']: print("Пора изменять stop-loss, новое значение {sl:0.8f}".format(sl=curr_rate_applied)) settings['stop_loss_fixed'] = curr_rate_applied else: # Текущая цена ниже или равна stop loss, продажа по рынку res = bot.createOrder( symbol=settings['symbol'], recvWindow=15000, side='SELL', type='MARKET', quantity=settings['amount'] ) print('Результат создания ордера', res) if 'orderId' in res: # Создание ордера прошло успешно, выход break else: # Выбрана стратегия Short, пытаемся купить монеты как можно выгоднее if curr_rate < settings['stop_loss_fixed']: print("Текущая цена ниже stop-loss") if curr_rate_applied < settings['stop_loss_fixed']: print("Пора изменять stop-loss, новое значение {sl:0.8f}".format(sl=curr_rate_applied)) settings['stop_loss_fixed'] = curr_rate_applied else: # Цена поднялась выше Stop-Loss, Покупка по рынку quantity = math.floor((settings['amount']/curr_rate)*(1/step_sizes[settings['symbol']]))/(1/step_sizes[settings['symbol']]) print("Цена поднялась выше Stop-Loss, Покупка по рынку, кол-во монет {quantity:0.8f}".format(quantity=quantity)) # math.Floor(coins*(1/stepSize)) / (1 / stepSize) res = bot.createOrder( symbol=settings['symbol'], recvWindow=15000, side='BUY', type='MARKET', quantity=quantity ) print('Результат создания ордера', res) if 'orderId' in res: # Создание ордера прошло успешно, выход break except Exception as e: print(e) time.sleep(1) # Ваш код тут # .... # .... if smth: # какое то там условие из индикаторов # тут на основе своих данных выбираете пару, тип ордера, курс, объем и т.п. curr_pair = 'EOSBTC' curr_amount = 0.0015 curr_rate = 0.1 # создаете ордер, покупаете монеты new_order = bot.createOrder( symbol=curr_pair, recvWindow=5000, side='BUY', type='LIMIT', timeInForce='GTC', # Good Till Cancel quantity=curr_amount, price=curr_rate, newOrderRespType='FULL' ) # Если ордер создался без ошибок, начинаем трейлинг продажи купленных монет if 'orderId' in new_order: settings = dict( symbol=curr_pair, # Пара для отслеживания strategy="Long", # Стратегия - Long (повышение), Short (понижение) stop_loss_perc = 0.5, # % оставания от цены stop_loss_fixed = 0, # Изначальный stop-loss, можно установить руками нужную сумму, потом бот подтянет. # Можно указать 0, тогда бот высчитает, возьмет текущую цену и применит к ней процент amount = curr_amount # Кол-во монет, которое планируем продать (в случае Long) или купить (в случае Short) # Если указываем Long, то альты для продажи (Например, продать 0.1 ETH в паре ETHBTC) # Если Short, то кол-во, на которое покупать, например купить на 0.1 BTC по паре ETHBTC ) # запускается функция и перехватыет управление на себя, когда она отработает процесс пойдет дальше process_trailing(settings) binance_api.py tv.py
  11. Можно каждую пару в отдельном потоке пускать, но все равно будет запаздывать. Поэтому нужно получать курсы по сокетам, в отдельном потоке, а в других потоках переставлять 🙂 Но проще запустить несколько скриптов одновременно и не париться
  12. А как вы сигналы получаете с виджетов?
  13. Версия 1.0.1

    12 скачиваний

    Побробное описание тут
  14. Так-с, ну собственно задача выполнена. Немного об ограничениях - сейчас берутся 100 самых свежих чатов, из-за особенностей работы АПИ. Можно сделать больше, но это нужно больше кода писать, сейчас не вижу в этом смысла. Оба канала - источник и приемник, должны быть в первой сотне. Можете их прикрепить, тогда они всегда гарантировано будут сверху. Можете захардкодить ID каналов, что бы сразу пересылать из одного в другой. Еще бот пересылает текстовые сообщения - пусть с картинками и прочим. Это большинство сообщений телеграмма в большинстве каналов, но бот не будет пересылать пост-картинку. Если выложили картинку, с описанием или нет, бот её проигнорит. Можно, конечно, добавить обработку и этого, но опять же нужно разбираться с этим и дописывать код. Ну и еще разного рода смайлики могут быть обрезаны/заменены, т.к. TK, на котором написан Idle, не может их отображать. Ну а в остальном всё работает из коробки и задел у такого большой, так что удачи, что бы вы там не планировали 🙂 Прикладываю файлы Клиент telegram, скрипт для копирования сообщений канала
  15. Этап 3 - непосредственно запуск и работа В директории C:\code\examples\telegram создайте файл main.py со следующим содержимым: # -*- coding: utf-8 -*- # # Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018 # # Distributed under the Boost Software License, Version 1.0. (See accompanying # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) # from ctypes.util import find_library from ctypes import * import json import sys API_KEY = 111111 API_HASH = '........' PHONE_NUMBER = '+7913212313' # load shared library tdjson_path = find_library("tdjson") or "tdjson.dll" if tdjson_path is None: print('can\'t find tdjson library') quit() tdjson = CDLL(tdjson_path) # load TDLib functions from shared library td_json_client_create = tdjson.td_json_client_create td_json_client_create.restype = c_void_p td_json_client_create.argtypes = [] td_json_client_receive = tdjson.td_json_client_receive td_json_client_receive.restype = c_char_p td_json_client_receive.argtypes = [c_void_p, c_double] td_json_client_send = tdjson.td_json_client_send td_json_client_send.restype = None td_json_client_send.argtypes = [c_void_p, c_char_p] td_json_client_execute = tdjson.td_json_client_execute td_json_client_execute.restype = c_char_p td_json_client_execute.argtypes = [c_void_p, c_char_p] td_json_client_destroy = tdjson.td_json_client_destroy td_json_client_destroy.restype = None td_json_client_destroy.argtypes = [c_void_p] td_set_log_file_path = tdjson.td_set_log_file_path td_set_log_file_path.restype = c_int td_set_log_file_path.argtypes = [c_char_p] td_set_log_max_file_size = tdjson.td_set_log_max_file_size td_set_log_max_file_size.restype = None td_set_log_max_file_size.argtypes = [c_longlong] td_set_log_verbosity_level = tdjson.td_set_log_verbosity_level td_set_log_verbosity_level.restype = None td_set_log_verbosity_level.argtypes = [c_int] fatal_error_callback_type = CFUNCTYPE(None, c_char_p) td_set_log_fatal_error_callback = tdjson.td_set_log_fatal_error_callback td_set_log_fatal_error_callback.restype = None td_set_log_fatal_error_callback.argtypes = [fatal_error_callback_type] # initialize TDLib log with desired parameters def on_fatal_error_callback(error_message): print('TDLib fatal error: ', error_message) td_set_log_verbosity_level(2) c_on_fatal_error_callback = fatal_error_callback_type(on_fatal_error_callback) td_set_log_fatal_error_callback(c_on_fatal_error_callback) # create client client = td_json_client_create() # simple wrappers for client usage def td_send(query): query = json.dumps(query).encode('utf-8') td_json_client_send(client, query) def td_receive(): result = td_json_client_receive(client, 1.0) if result: result = json.loads(result.decode('utf-8')) return result def td_execute(query): query = json.dumps(query).encode('utf-8') result = td_json_client_execute(client, query) if result: result = json.loads(result.decode('utf-8')) return result td_send({'@type': 'getAuthorizationState', '@extra': 1.01234}) chat_ids = [] chats = [] choosen_chat_id = 0 non_bmp_map = dict.fromkeys(range(0x10000, sys.maxunicode + 1), 0xfffd) # main events cycle while True: event = td_receive() if event: # if client is closed, we need to destroy it and create new client if event['@type'] == 'updateAuthorizationState' and event['authorization_state']['@type'] == 'authorizationStateClosed': break if event['@type'] in ['updateSupergroup', 'updateNewChat', 'updateChatLastMessage', 'updateUser']: continue if event.get('@extra') == 1001001: chat_ids = event['chat_ids'] for chat_id in chat_ids: td_send({'@type':'getChat', 'chat_id':chat_id, 'extra':1001011}) if event['@type'] == 'updateNewMessage' and event['message']['chat_id'] == choosen_chat_id: message_type = event['message']['content']['@type'] print("*"*80) print("Получено:", message_type) print("-"*80) if message_type == 'messageText': message_text = event['message']['content']['text']['text'].translate(non_bmp_map) print(message_text) td_send({'@type':'sendMessage', 'chat_id':target_chat_id, 'input_message_content': { '@type': 'inputMessageText', 'text': { '@type': 'formattedText', 'text': message_text }}} ) print("-"*80) print(event) print("*"*80) if event['@type'] == 'chat': title = event['title'].translate(non_bmp_map) print('Получен чат', len(chats), title, event['id']) chats.append({'title': title, 'id': event['id']}) if len(chats) == len(chat_ids): chat_id = int(input('Выберите чат для мониторинга (1 - {m_ch})'.format(m_ch=len(chats)))) print("Выбран чат", chats[chat_id]) choosen_chat_id = chats[chat_id]['id'] chat_id = int(input('Выберите чат для пересылки (1 - {m_ch})'.format(m_ch=len(chats)))) print("Выбран чат", chats[chat_id]) target_chat_id = chats[chat_id]['id'] if target_chat_id == choosen_chat_id: print("Нельзя два раза выбрать одно и то же!!!!") break if event['@type'] == "authorizationStateWaitTdlibParameters": td_send({'@type': 'setTdlibParameters', 'parameters': {'use_test_dc': False, 'api_id':API_KEY, 'api_hash': API_HASH, 'device_model': 'Desktop', 'system_version': 'Unknown', 'application_version': "0.0", 'system_language_code': 'en', 'database_directory': 'Database', 'files_directory': 'Files', 'use_file_database': True, 'use_chat_info_database': True, 'use_message_database': True, } }) td_send({'@type': 'checkDatabaseEncryptionKey',}) elif event['@type'] == 'updateAuthorizationState' and event['authorization_state']['@type'] == 'authorizationStateWaitPhoneNumber': td_send({'@type': 'setAuthenticationPhoneNumber', 'phone_number': PHONE_NUMBER}) elif event['@type'] == 'updateAuthorizationState' and event['authorization_state']['@type'] == 'authorizationStateWaitCode': code = input("Enter code:") td_send({'@type': 'checkAuthenticationCode', 'code': code}) elif event['@type'] == 'updateAuthorizationState' and event['authorization_state']['@type'] == 'authorizationStateReady': td_send({'@type': 'getChats', 'limit': 100, 'offset_order':2**63-1, '@extra': 1001001}) td_send({'@type': 'getMe', '@extra': 1001111}) sys.stdout.flush() td_json_client_destroy(client) Я взял пример из C:\code\examples\telegram\src\example\python и подогнал под себя. Тут смысл такой - вам нужно в строках API_KEY = 111111 API_HASH = '........' PHONE_NUMBER = '+7913212313' указать API_KEY и Hash из телеграмма, которые вы получили на этапе 2. Так же нужно указать свой номер, под которым вы зарегистрированы в телеграмме. Для чистоты эксперимента желательно что бы телеграм был запущен у вас на компе или телефоне, что бы туда пришел код подтверждения - через СМС я не добавлял. Этот скрипт нужно запустить из питона 64 битной версии! Это важно. Открываете в Idle, меняете апи-ключи и телефон и нажимаете F5 - скрипт запускается, при первом запуске должна появиться надпись Enter code: А в телеграм придет сообщение с кодом. Введите код, и в телеграм придет второе сообщение о найденом новом устройстве. Потом, и при любом другом запуске, вам будет выдаваться список из 100 ваших чатов, примерно в том же порядке, в каком вы их видите в телеграмме, сначала прикрепленные чаты, потом самые свежеобновленные. А потом, на основании списка, вам будет предложено выбрать чат/канал источник, и чат/канал, куда пересылать сообщения В указанном примере, все текстовые сообщения из канала Mash будут от моего имени переправляться в группу Баблофил. Разумеется, это только для примера.
×
×
  • Создать...