Показаны сообщения с ярлыком python. Показать все сообщения
Показаны сообщения с ярлыком python. Показать все сообщения

суббота, 19 мая 2018 г.

Как быстро скачать котировки с IEX

Как быстро скачать котировки с IEX
# -*- coding: utf-8 -*-
import pycurl
import requests
import json
import time
import os

#def performMyMulti(tools_, time_frame = '1m'):
def performMyMulti(tools_, time_frame = '5y'):
    '''
    Функция многопоточного скачивания. Принимает на вход список
    кодов инструментов для скачивания. Количество инструментов в этом
    списке не должно превышать 100шт.
    '''
    m = pycurl.CurlMulti()
    m.handles = []
    files = [] # список файлов для сохранения результатов

    start_ = time.time() # замер времени для расчета скорости, начальная точка
    # создание и настройка curl-объектов
    for tool_ in tools_:
        c = pycurl.Curl()

        # имя файла для сохранения результатов; файлы сохраняются в каталог data
        fileName = "data%s%s_%s.txt" % (os.sep, tool_, time_frame)
        fileName = fileName.replace('*', '_')
        f = open(fileName, "wb")
        files.append(f) # файл добавляется в список, чтобы потом закрыть его
        c.setopt(c.WRITEDATA, f) # кроме файла здесь можно указывать функцию, но файл нам наиболее удобен
        url = "https://api.iextrading.com/1.0/stock/%s/chart/%s" % (tool_, time_frame)
        c.setopt(pycurl.URL, url)

        m.add_handle(c)
        m.handles.append(c)

    num_handles = len(m.handles)
    while num_handles:
        while 1:
            # выполнить запросы
            ret, num_handles = m.perform()
            if ret != pycurl.E_CALL_MULTI_PERFORM:
                break
        m.select(1.0)

    # очистка
    for c in m.handles:
        c.close()
        m.remove_handle(c)

    for f in files:
        f.close()

    m.close()
    del m.handles
    end_ = time.time() # замер времени для расчета скорости, конечная точка

    return len(tools_) / (end_-start_) # скорость в секунду

# скачиваем список инструментов
r = requests.get('https://api.iextrading.com/1.0/ref-data/symbols')
data = json.loads(r.text)
tools = [] #список кодов инструментов
# выбираем коды инструментов в отдельный массив
for tool in data:
    try:
        if tool['isEnabled'] is True:
            tools.append(tool['symbol'])
    except:
        continue

block = 80 #количество параллельных запросов (не более 100шт)

tools_count = len(tools)
print(u"Всего инструментов для скачивания: %d" % tools_count)
loops = tools_count / block # количество полных циклов (циклов по block запросов)
loops =int(loops)
print('loops = ', loops)
tail = tools_count % block # количество оставшихся запросов
tools_ok = 0 # общее количество выполненных запросов
start = time.time() # замер общего времени, начальная точка
for i in range(loops): # в цикле по всем полным циклам
    srez = tools[i*block:i*block+block:1] # формируем выборку из следующих block инструментов
    speed = performMyMulti(srez) # выполняем параллельное скачивание
    tools_ok += block
    print(u"готово %d из %d, скорость %f в сек" % (tools_ok, tools_count, speed))
if tail > 0: # "докачиваем" оставшиеся инструменты
    i += 1
    srez = tools[block*i:block*i+tail]
    speed = performMyMulti(srez)
    tools_ok += tail
    print(u"готово %d из %d, скорость %f в сек" % (tools_ok, tools_count, speed))
end = time.time() # замер общего времени, конечная точка
print(u"Всё скачали! Ушло %f сек" % (end-start))

понедельник, 26 марта 2018 г.

Вывод в excel

import openpyxl
from openpyxl import Workbook
import os, errno


dat ={}
def put_excel(index, name, val):
    global dat
    dat[index] =  {'name':name,'val':val}

def put_name():
    global dat
    fg = []
    for key in dat.keys():
        fg.append(dat[key]['name'])
    ws.append(fg)

def put_val():
    global dat
    fg = []
    for key in dat.keys():
        fg.append(dat[key]['val'])
    ws.append(fg)


wb = Workbook()
ws = wb.active

# описываем заголовки таблицы:
# в такой последовательности будут выводится
put_excel(1,'open', 0)
put_excel(2,'high', 0)
put_excel(3,'low',  0)
put_excel(4,'close', 0)

#выводим заголовки в таблицу
put_name()

i=1
while i  <  5:
    put_excel(1,'open', 10+i)
    put_excel(2,'high', 20+i)
    put_excel(3,'low',  30+i)
    put_excel(4,'close', 40+i)
    i=i+1
    # выводим строку со значениями
    put_val()


wb.save(os.path.dirname(os.path.abspath(__file__)) + "/excel.xlsx")

пятница, 23 марта 2018 г.

ubuntu 16.04 python3-openpyxl

$ sudo apt update
$ sudo apt upgrade
$ sudo apt install python3-openpyxl

import openpyxl
import os
from openpyxl import Workbook

#try:
    #os.remove( "./exmo_excel.xlsx"))
#except OSError as e: # this would be "except OSError, e:" before Python 2.6
    #if e.errno != errno.ENOENT: # errno.ENOENT = no such file or directory
        #raise # re-raise exception if a different error occurred
#l = open("./tester.txt", 'a', encoding='utf-8')

# Создадим Excel файл
wb = Workbook()
ws = wb.active
# Вставим заголовки
ws.append(["Дата", "ID", "Тип сделки", "Кол-во", "Цена", "Сумма"])

# Сохраняем файл
wb.save(os.path.dirname(os.path.abspath(__file__)) + "/excel.xlsx")

среда, 21 марта 2018 г.

Cвечи plx

Особенности формирования неполной свечи,
Неполная свеча появляется когда в sql запрос попадает хотя бы одна сделка
а неполном периоде:
timestamp x =  1521933300

Расчет свечей из кэша :
data1 = [{'date': 1521929700, 'open': 8640.0, 'high': 8717.0, 'low': 8610.81133606, 'close': 8694.24124667}, {'date': 1521930600, 'open': 8694.24124712, 'high': 8719.44583815, 'low': 8650.76841592, 'close': 8667.85584522}, {'date': 1521931500, 'open': 8667.83364934, 'high': 8683.19046025, 'low': 8613.02673386, 'close': 8630.0}, {'date': 1521932400, 'open': 8630.0, 'high': 8653.33548722, 'low': 8610.81133606, 'close': 8653.33548722}]
cand2_st =  1521933300
cand2_end =  1521933300

data2= []

Удаляем последнюю свечу
data1 = [{'date': 1521929700, 'open': 8640.0, 'high': 8717.0, 'low': 8610.81133606, 'close': 8694.24124667}, {'date': 1521930600, 'open': 8694.24124712, 'high': 8719.44583815, 'low': 8650.76841592, 'close': 8667.85584522}, {'date': 1521931500, 'open': 8667.83364934, 'high': 8683.19046025, 'low': 8613.02673386, 'close': 8630.0}, {'date': 1521932400, 'open': 8630.0, 'high': 8653.33548722, 'low': 8610.81133606, 'close': 8653.33548722}]

Добавим последню свечу
Если data2 не пустой
Список в работу целиком :
data1 = [{'date': 1521929700, 'open': 8640.0, 'high': 8717.0, 'low': 8610.81133606, 'close': 8694.24124667}, {'date': 1521930600, 'open': 8694.24124712, 'high': 8719.44583815, 'low': 8650.76841592, 'close': 8667.85584522}, {'date': 1521931500, 'open': 8667.83364934, 'high': 8683.19046025, 'low': 8613.02673386, 'close': 8630.0}, {'date': 1521932400, 'open': 8630.0, 'high': 8653.33548722, 'low': 8610.81133606, 'close': 8653.33548722}]
—---------------------------------------------------------------------------------------------------------------------------------—
timestamp x =  1521933310
Расчет свечей из кэша :
data1 = [{'date': 1521930600, 'open': 8694.24124712, 'high': 8719.44583815, 'low': 8650.76841592, 'close': 8667.85584522}, {'date': 1521931500, 'open': 8667.83364934, 'high': 8683.19046025, 'low': 8613.02673386, 'close': 8630.0}, {'date': 1521932400, 'open': 8630.0, 'high': 8653.33548722, 'low': 8610.81133606, 'close': 8653.33548722}, {'date': 1521933300, 'open': 8653.13572438, 'high': 8653.13572438, 'low': 8653.13572438, 'close': 8653.13572438}]
cand2_st =  1521933300
cand2_end =  1521933310

data2= [{'date': 1521933300, 'open': 8653.13572438, 'high': 8653.13572438, 'low': 8653.13572438, 'close': 8653.13572438}]

Удаляем последнюю свечу
data1 = [{'date': 1521930600, 'open': 8694.24124712, 'high': 8719.44583815, 'low': 8650.76841592, 'close': 8667.85584522}, {'date': 1521931500, 'open': 8667.83364934, 'high': 8683.19046025, 'low': 8613.02673386, 'close': 8630.0}, {'date': 1521932400, 'open': 8630.0, 'high': 8653.33548722, 'low': 8610.81133606, 'close': 8653.33548722}, {'date': 1521933300, 'open': 8653.13572438, 'high': 8653.13572438, 'low': 8653.13572438, 'close': 8653.13572438}]

Добавим последню свечу
Если data2 не пустой
Список в работу целиком :
data1 = [{'date': 1521930600, 'open': 8694.24124712, 'high': 8719.44583815, 'low': 8650.76841592, 'close': 8667.85584522}, {'date': 1521931500, 'open': 8667.83364934, 'high': 8683.19046025, 'low': 8613.02673386, 'close': 8630.0}, {'date': 1521932400, 'open': 8630.0, 'high': 8653.33548722, 'low': 8610.81133606, 'close': 8653.33548722}, {'date': 1521933300, 'open': 8653.13572438, 'high': 8653.13572438, 'low': 8653.13572438, 'close': 8653.13572438}]


# candel_polo_5x.py
import time
import json
import requests
import urllib, http.client
import hmac, hashlib
import mysql.connector
import sys
import os, errno
import calendar
import numpy
import talib

from datetime import datetime

#Начало и конец свечей PERIOD1  # get_ticks (cand1_st, cand1_end, PERIOD1)
#MACD=26
MACD=2

PERIOD = 15 # минут
cand1_st = calendar.timegm((2018, 3, 24, 22, 0, 0, 0, 0, 0)) # время UTC
cand1_end = calendar.timegm((2018, 3, 25, 2, 0, 0, 0, 0, 0)) # время UTC

#1518628155 Начало базы 2018-02-14 20:09:15
#print('Начало базы', datetime.fromtimestamp(1518628155))
#Установим дату и время начала тестирования
#time_start = (2018, 1, 1, 0, 0, 0, 0, 0, 0) #Время UTC
time_start = (2018, 3, 24, 23, 0, 0, 0, 0, 0) #Время UTC

#timestampstart = time.mktime(time_start) #Локальное время
timestampstart = calendar.timegm(time_start) # время UTC
x=timestampstart
#x=1509494400
#x=1509494399
#x=1521932451
#x=1521932400
#x=1521932401
#x=1521933300
#x=1521933299
x=1521933300

print('Начало тестирования utc ', datetime.utcfromtimestamp(timestampstart))
#Установим дату и время завершения тестирования
#time_end = (2018, 3, 20, 0, 0, 0, 0, 0, 0) #Время UTC
time_end = (2018, 3, 25, 1, 0, 0, 0, 0, 0) #Время UTC
#time_end = (2018, 3, 13, 15, 0, 0, 0, 0, 0) #Время UTC
#time_end = (2018, 3, 20, 5, 0, 0, 0, 0, 0) #Время UTC
#timestampend = time.mktime(time_end) #Локальное время
timestampend = calendar.timegm(time_end) # время UTC
print('Заввершение тестирования utc ', datetime.utcfromtimestamp(timestampend))
y=timestampend

USE_LOG = True
DEBUG = False # True - выводить отладочную информацию, False - писать как можно меньше
numpy.seterr(all='ignore')


# Свой класс исключений
class ScriptError(Exception):
    pass
class ScriptQuitCondition(Exception):
    pass
    
def is_nan(x):
    return (x is numpy.nan or x != x)


# Получаем данные, необходимые для построения индикаторов
#def get_ticks(pair):
def get_sql(st, end, PER):
    #global y
    #global x
    #_SQL = """select * from trade"""
    #x=int(time.time())
    #print('y = ',y)
    #print(datetime.fromtimestamp(y))
    pr = PER * 60
    #x= y - pr*50  #Для построения MACD требуется примерно 50 периодов свечей
    #_SQL = """select * from trade where date between 1519318790 and 1519318800; """
    _SQL = """SELECT
                    FLOOR(MIN(`date`)/%s)*%s AS date,
                    SUBSTRING_INDEX(MIN(CONCAT(`date`, '_', id, '_', rate)), '_', -1) AS `open`,
                    MAX(rate) AS high,
                    MIN(rate) AS low,
                    SUBSTRING_INDEX(MAX(CONCAT(`date`, '_', id, '_', rate)), '_', -1) AS `close`
              FROM trade
              WHERE date >= %s and date <= %s
              GROUP BY FLOOR(`date`/%s)
              ORDER BY date"""

    db = mysql.connector.connect(host="localhost", user="u", passwd="secret", db="polo")
    #db = mysql.connector.connect(host="10.8.1.1", user="u", passwd="secret", db="exmo")
    cur = db.cursor()
    try:
        cur.execute(_SQL,(pr,pr,st,end,pr))
        sdata=[]
        for item in cur.fetchall():
            sdata.append({'date':int(item[0]),'open':float(item[1]),'high':float(item[2]),'low':float(item[3]),'close':float(item[4])})
    except Exception as e:
        log(e)
    cur.close()
    db.close()
    #print(sdata)
    return sdata

# Выводит всякую информацию на экран, самое важное скидывает в Файл log.txt
def log(*args):
    if USE_LOG:
        l = open("./candel_polo.txt", 'a', encoding='utf-8')
        print(datetime.now(), *args, file=l)
        #print(datetime.fromtimestamp(y+3*60*60), *args, file=l) #Локальное время
        #print(datetime.utcfromtimestamp(y), *args, file=l)  #UTC

        l.close()
    print(datetime.now(),' ', *args)
    #print(datetime.fromtimestamp(y+3*60*60),' ', *args) #Локальное время
    #print(datetime.utcfromtimestamp(y),' ', *args) #UTC

def get_ticks (d, data, flg):
    global PERIOD
    global MACD
    # d текщее время на которое расчитывается свеча
    # data список предварительно рассчитанные свечи
    DEBUG = True
    if flg: #flg = True для ускорения используем кэш предрасчитанные свечи в списке data
        data1=[] #перегрузим  сюда свечи  до времени d с учетом запаса для расчета MACD
        for offset, elem in enumerate(data):
            #if True:
            if (data[offset]['date'] <=d) and (data[offset]['date'] >= (d - PERIOD*MACD*2*60)):
                data1.append(data[offset]) #не пропускаем последнюю свечу!
        cand2_st = data1[-1]['date'] # из последней свечи возьмем возьмем начала периода для расчета неполной свечи
        cand2_end = d # время UTC
        data2=get_sql(cand2_st, cand2_end, PERIOD) #расчет неполной свечи на момент d
        data1.pop() #удалим последнюю, полную закрытую свечу
        if len(data2)>0: # при расчете свечи на момент d может вернуться пустой список (если сделок не было)
            data1.append(data2[-1])
        if DEBUG: #отладка
            print()
            print('Расчет свечей из кэша :')
            print('data1 =', data1)
            print('cand2_st = ', cand2_st)
            print('cand2_end = ', cand2_end)
            print()
            print('data2=',data2)
            print()
            print("Удаляем последнюю свечу")
            print('data1 =', data1)
            print()
            print('Добавим последню свечу')
            print('Если data2 не пустой')
            print('Список в работу целиком :')
            print('data1 =', data1)
        return data1
    else: #flg = False свечи рассчитываются напрямую запросом sql
        cand2_st = d - PERIOD*MACD*2*60 # время UTC
        cand2_end = d # время UTC
        data2=get_sql(cand2_st, cand2_end, PERIOD)
        if DEBUG:# отладка
            print()
            print('Тоже напрямую через SQL :')
            print('cand2_st = ', cand2_st)
            print('cand2_end = ', cand2_end)
            print()
            print('data2 =', data2)
        return data2



log('свечи PERIOD = ',PERIOD, ' мин')
#log('начало запроса', datetime.utcfromtimestamp(x))
#log('окончание запроса', datetime.utcfromtimestamp(y))
#print('Начало запроса',datetime.now()) #UTC
data=get_sql(cand1_st, cand1_end, PERIOD)
#print(data)
#print('Конец запроса', datetime.now()) #UTC
#print(data)
print('текущее время x',datetime.utcfromtimestamp(x)) #UTC
print('timestamp x = ',x)

#while True:
data1=get_ticks(x, data, True)
#data1=get_ticks(x, data, False)
x=1521933310
data1=get_ticks(x, data, True)


#print(data1[-1])
#print(data1)
#x = x +3600

#x=x+1
#data2=get_sql(x-100, x, PERIOD)
#print(data2)

Заполнение базы plx

#sql_pol.1.4.py
#import numpy
#import talib
import requests
import json
import time
import calendar
import mysql.connector
import sys
from datetime import datetime
#from matplotlib.finance import candlestick2_ohlc
#i#mport matplotlib.animation as animation
#import matplotlib.pyplot as plt
#import matplotlib.ticker as ticker
from datetime import datetime
k=0
NO_DATA = False

def get_date(str_date):
    #https://pythonworld.ru/moduli/modul-time.html
    #print(str_date)
    t1=time.strptime(str_date,'%Y-%m-%d %H:%M:%S')
    #print(t1)
    t2 = calendar.timegm(t1)
    #print(t2)
    #print(datetime.utcfromtimestamp(t2))
    return t2


def get_polo():
    global NO_DATA
    global k
    global st_time
    global end_time
    pair = 'USDT_BTC'
    time.sleep(0.2)
    #chart_data={}
    #manual http://docs.python-requests.org/en/master/user/advanced/#request-and-response-objects
    while True:
        try:
            log('requests.get')
            #response  = requests.get('https://poloniex.com/public?command=returnTradeHistory&currencyPair=%s&start=%s&end=%s' % (pair,st_time,end_time), timeout = None)
            response  = requests.get('https://poloniex.com/public?command=returnTradeHistory&currencyPair=%s&start=%s&end=%s' % (pair,st_time,end_time), timeout = 5)
            log('response.status_code =', response.status_code)
            if response.status_code == 200:
                break
            else:
                log('response.status_code =', response.status_code)
        except Exception as e:
            log(e)
    chart_data = json.loads(response.text)
    k=-1
    if type(chart_data) is list:
        k = len(chart_data)
    #print('st_time = ', st_time)
    #print('end_time = ', end_time)
    #print('k = ',k)
    print(chart_data[-1])
    return chart_data


def update_trade(data):
    PAIR = 'BTC_USD'
    db = mysql.connector.connect(host="localhost", user="u", passwd="secret", db="polo")
    cur = db.cursor()
    #[{'globalTradeID': 355563163, 'tradeID': 20847088, 'date': '2018-03-20 17:31:49', 'type': 'buy', 'rate': '8775.87720002', 'amount': '0.00131316', 'total': '11.52413090'}]   
    #print(data)
    try:
        for item in reversed(data):
            _SQL = """insert ignore into trade
                      (gtrade_id, trade_id, date, type, rate, amount, total)
                      values
                      (%s,%s,%s,%s,%s,%s,%s)"""
            cur.execute(_SQL, (item['globalTradeID'], item['tradeID'], get_date(item['date']), item['type'], item['rate'], item['amount'],item['total']))
            db.commit()
    except Exception as e:
        log(e)
    cur.close()
    db.close()


def verify_trade():
    global st_time
    global end_time
    db = mysql.connector.connect(host="localhost", user="u", passwd="secret", db="polo")
    cur = db.cursor()
    try:
        _SQL = """select count(1) FROM trade
                  WHERE (date >=  %s and date <= %s)"""
        cur.execute(_SQL,(st_time, end_time))
        arr = cur.fetchall()
        #print(arr)
        #print('число записей ', arr[0][0])
        db.commit()
        return int(arr[0][0])
    except Exception as e:
        log(e)
    cur.close()
    db.close()

def update_verify():
    global st_time
    global end_time
    global k
    db = mysql.connector.connect(host="localhost", user="u", passwd="secret", db="polo")
    cur = db.cursor()
    try:
        _SQL = """insert ignore into  verify
                  (st_time, end_time, count)
                  values (%s,%s,%s)"""
        cur.execute(_SQL, (st_time, end_time, k))
        db.commit()
    except Exception as e:
        log(e)
    cur.close()
    db.close()

def get_end_time():
    db = mysql.connector.connect(host="localhost", user="u", passwd="secret", db="polo")
    cur = db.cursor()
    try:
        _SQL = """select end_time from  verify
                  order by end_time desc limit 1"""
        cur.execute(_SQL)
        arr = cur.fetchall()
        #print(arr)
        #print('число записей ', arr[0][0])
        db.commit()
        return int(arr[0][0])
    except Exception as e:
        log(e)
    cur.close()
    db.close()

def count_verify():
    db = mysql.connector.connect(host="localhost", user="u", passwd="secret", db="polo")
    cur = db.cursor()
    try:
        _SQL = """select count(1) FROM verify"""
        cur.execute(_SQL)
        arr = cur.fetchall()
        #print(arr)
        #print('число записей ', arr[0][0])
        db.commit()
        return int(arr[0][0])
    except Exception as e:
        log(e)
    cur.close()
    db.close()

def log(*args):
    #if USE_LOG:
    l = open("./sql_pol.txt", 'a', encoding='utf-8')
    print(datetime.now(), *args, file=l)
    #print(datetime.fromtimestamp(y), *args, file=l) #Локальное время
    #print(datetime.utcfromtimestamp(y), *args, file=l) #UTC
    l.close()
    print(datetime.now(),' ', *args)
    #print(datetime.fromtimestamp(y+3*60*60),' ', *args)
    #print(datetime.utcfromtimestamp(y),' ', *args)


   
#Установим дату и время начала заполнения
# UTC
time_start = (2017, 1, 1, 0, 0, 0, 0, 0, 0)  #Время UTC
timestampstart = calendar.timegm(time_start) # время UTC
#Установим дату и время завершения заполнения
#UTC
if False: #True -заданное время  False текущее
    time_end = (2018, 3, 23, 20, 0, 0, 0, 0, 0) #Время UTC
    timestampend = calendar.timegm(time_end) # время UTC
else:
    timestampend  = time.time()
print('Время завершения выполнения', datetime.utcfromtimestamp(timestampend))


timeplus = 3600
st_time=timestampstart
log('count_verify()= ', count_verify())
if count_verify() > 0:
    log('get_end_time() = ', get_end_time())
    st_time=get_end_time() + 1
    log('Продолжаем работу c ', datetime.utcfromtimestamp(st_time))
log('Начало')
# Бесконечный цикл процесса - основная логика
#update_mysql(get_polo())
#if False:
if True:
    while True:
        #i=1
        #while i<5:
        try:
            if st_time > timestampend:
                log('Завершение заполнения базы', datetime.fromtimestamp(timestampend))
                sys.exit()
            #print('st_time = ', st_time)
            end_time=st_time+timeplus
            #print('end_time = ', end_time)
            i = 0
            while  i < 10 :
                try:
                    Flag = False
                    data=get_polo()
                    if type(data) is list:
                        Flag = True
                        if len(data) > 0:
                            update_trade(data)
                            count=verify_trade()
                            log('Верифицировано!') #Добавляем в sql запись
                            log('с ', datetime.utcfromtimestamp(st_time))
                            log('по ', datetime.utcfromtimestamp(end_time))
                            log('Количество записей ',k)
                            update_verify()
                            k=0
                            break
                        else:
                            log('Список нулевой длины  len(data) :',len(data))
                    else:
                        Flag = False
                        print('type(data) : ', type(data))
                    i = i + 1
                except Exception as e:
                    log(e)
                    time.sleep(1)
            if not Flag :
                log('Аварийное Завершение заполнения базы', datetime.fromtimestamp(st_time))
                log('Попытки получить данные из интернета неудачны')
                sys.exit()
            if k  > 0 :
                update_trade(data)
                count=verify_trade()
            else:
                count = 0
            if count == k :
                log('Верифицировано!') #Добавляем в sql запись
                log('с ', datetime.utcfromtimestamp(st_time))
                log('по ', datetime.utcfromtimestamp(end_time))
                #print('st_time = ', st_time)
                #print('end_time = ', end_time)
                log('Количество записей ',k)
                update_verify()
                k=0
            else:
                log('Аварийное Завершение заполнения базы', datetime.fromtimestamp(st_time))
                log('Не совпадение количества записе!')
                sys.exit()
            st_time=end_time+1 #Предполагаем что правая  граница  на polonix
            time.sleep(1)
            #i=i+1
        except Exception as e:
            log(e)

вторник, 20 марта 2018 г.

Настройка базы

https://poloniex.com/public?command=returnTradeHistory&currencyPair=USDT_BTC&start=1518628155&end=1518629000

$ sudo mysql -u root -p
(Можно задать пароль)

MariaDB [(none)]> create database polo;

Задать учетную запись u для базы polo с паролем secret

MariaDB [(none)]> grant all on polo.* to 'u' identified by 'secret';

MariaDB [(none)]> quit

$ mysql -u u -p polo

MariaDB [exmo]> create table trade (
id int auto_increment primary key,
ts timestamp default current_timestamp,
gtrade_id int not null,
trade_id int not null,
date int not null,
type varchar(4) not null,
rate decimal(30,8) not null,
amount decimal(30,8) not null,
total decimal(30,8) not null );

MariaDB [polo]> CREATE UNIQUE INDEX gtrade_id ON trade(gtrade_id);
MariaDB [polo]> CREATE UNIQUE INDEX trade_id ON trade(trade_id);
MariaDB [polo]> CREATE INDEX date ON trade(date);
MariaDB [polo]> CREATE INDEX rate ON trade(rate);
 
MariaDB [polo]> describe trade;
+-----------+---------------+------+-----+-------------------+----------------+
| Field     | Type          | Null | Key | Default           | Extra          |
+-----------+---------------+------+-----+-------------------+----------------+
| id        | int(11)       | NO   | PRI | NULL              | auto_increment |
| ts        | timestamp     | NO   |     | CURRENT_TIMESTAMP |                |
| gtrade_id | int(11)       | NO   | UNI | NULL              |                |
| trade_id  | int(11)       | NO   | UNI | NULL              |                |
| date      | int(11)       | NO   | MUL | NULL              |                |
| type      | varchar(4)    | NO   |     | NULL              |                |
| rate      | decimal(30,8) | NO   | MUL | NULL              |                |
| amount    | decimal(30,8) | NO   |     | NULL              |                |
| total     | decimal(30,8) | NO   |     | NULL              |                |
+-----------+---------------+------+-----+-------------------+----------------+

9 rows in set (0.00 sec)
 
  
$ mysql -u u -p polo



MariaDB [exmo]> create table verify ( 
id int auto_increment primary key,
ts timestamp default current_timestamp,
st_time int not null,
end_time int not null,
count int not null);
  
MariaDB [polo]> CREATE UNIQUE INDEX end_time ON verify(end_time);
 
MariaDB [polo]> describe verify;
+----------+-----------+------+-----+-------------------+----------------+
| Field    | Type      | Null | Key | Default           | Extra          |
+----------+-----------+------+-----+-------------------+----------------+
| id       | int(11)   | NO   | PRI | NULL              | auto_increment |
| ts       | timestamp | NO   |     | CURRENT_TIMESTAMP |                |
| st_time  | int(11)   | NO   |     | NULL              |                |
| end_time | int(11)   | NO   | UNI | NULL              |                |
| count    | int(11)   | NO   |     | NULL              |                |
+----------+-----------+------+-----+-------------------+----------------+
5 rows in set (0.00 sec)
 
  
MariaDB [polo]> delete from  verify; 
 
MariaDB [polo]> delete from  trade;
Query OK, 15 rows affected (0.00 sec)
 
python3 sql_pol.py
k =  13
[{'globalTradeID': 355582604, 'tradeID': 20851900, 'date': '2018-03-20 18:33:30',
 'type': 'buy', 'rate': '8805.27999977', 'amount': '0.01230000', 'total': '108.30494399'},
 {'globalTradeID': 355582602, 'tradeID': 20851899, 'date': '2018-03-20 18:33:29',
 'type': 'sell', 'rate': '8805.00000000', 'amount': '0.00017037', 'total': '1.50010785'},
 {'globalTradeID': 355582601, 'tradeID': 20851898, 'date': '2018-03-20 18:33:29',
 'type': 'sell', 'rate': '8805.00000000', 'amount': '0.00017037', 'total': '1.50010785'},
 {'globalTradeID': 355582599, 'tradeID': 20851897, 'date': '2018-03-20 18:33:29',
 'type': 'sell', 'rate': '8805.00000000', 'amount': '0.00017037', 'total': '1.50010785'},
 {'globalTradeID': 355582597, 'tradeID': 20851896, 'date': '2018-03-20 18:33:29',
 'type': 'sell', 'rate': '8805.00000000', 'amount': '0.00017037', 'total': '1.50010785'},
 {'globalTradeID': 355582593, 'tradeID': 20851895, 'date': '2018-03-20 18:33:28',
 'type': 'buy', 'rate': '8805.27999978', 'amount': '0.00085355', 'total': '7.51574674'},
 {'globalTradeID': 355582583, 'tradeID': 20851894, 'date': '2018-03-20 18:33:26',
 'type': 'sell', 'rate': '8805.00000000', 'amount': '0.00028395', 'total': '2.50017975'},
 {'globalTradeID': 355582581, 'tradeID': 20851893, 'date': '2018-03-20 18:33:26',
 'type': 'sell', 'rate': '8805.00000000', 'amount': '0.00028395', 'total': '2.50017975'},
 {'globalTradeID': 355582579, 'tradeID': 20851892, 'date': '2018-03-20 18:33:26',
 'type': 'sell', 'rate': '8805.00000000', 'amount': '0.00017037', 'total': '1.50010785'},
 {'globalTradeID': 355582578, 'tradeID': 20851891, 'date': '2018-03-20 18:33:26',
 'type': 'sell', 'rate': '8805.00000000', 'amount': '0.00028395', 'total': '2.50017975'},
 {'globalTradeID': 355582577, 'tradeID': 20851890, 'date': '2018-03-20 18:33:26',
 'type': 'sell', 'rate': '8805.00000000', 'amount': '0.00028395', 'total': '2.50017975'},
 {'globalTradeID': 355582576, 'tradeID': 20851889, 'date': '2018-03-20 18:33:26',
 'type': 'buy', 'rate': '8805.27999980', 'amount': '0.00400478', 'total': '35.26320923'},
 {'globalTradeID': 355582571, 'tradeID': 20851888, 'date': '2018-03-20 18:33:25',
 'type': 'buy', 'rate': '8805.27999980', 'amount': '0.00136569', 'total': '12.02528284'}]
 
MariaDB [polo]> select * from trade;
MariaDB [polo]> select * from trade;
+----+---------------------+-----------+----------+------------+------+---------------+------------+--------------+
| id | ts                  | gtrade_id | trade_id | date       | type | rate          | amount     | total        |
+----+---------------------+-----------+----------+------------+------+---------------+------------+--------------+
| 52 | 2018-03-20 21:33:36 | 355582571 | 20851888 | 1521570805 | buy  | 8805.27999980 | 0.00136569 |  12.02528284 |
| 53 | 2018-03-20 21:33:36 | 355582576 | 20851889 | 1521570806 | buy  | 8805.27999980 | 0.00400478 |  35.26320923 |
| 54 | 2018-03-20 21:33:36 | 355582577 | 20851890 | 1521570806 | sell | 8805.00000000 | 0.00028395 |   2.50017975 |
| 55 | 2018-03-20 21:33:36 | 355582578 | 20851891 | 1521570806 | sell | 8805.00000000 | 0.00028395 |   2.50017975 |
| 56 | 2018-03-20 21:33:36 | 355582579 | 20851892 | 1521570806 | sell | 8805.00000000 | 0.00017037 |   1.50010785 |
| 57 | 2018-03-20 21:33:36 | 355582581 | 20851893 | 1521570806 | sell | 8805.00000000 | 0.00028395 |   2.50017975 |
| 58 | 2018-03-20 21:33:36 | 355582583 | 20851894 | 1521570806 | sell | 8805.00000000 | 0.00028395 |   2.50017975 |
| 59 | 2018-03-20 21:33:36 | 355582593 | 20851895 | 1521570808 | buy  | 8805.27999978 | 0.00085355 |   7.51574674 |
| 60 | 2018-03-20 21:33:36 | 355582597 | 20851896 | 1521570809 | sell | 8805.00000000 | 0.00017037 |   1.50010785 |
| 61 | 2018-03-20 21:33:36 | 355582599 | 20851897 | 1521570809 | sell | 8805.00000000 | 0.00017037 |   1.50010785 |
| 62 | 2018-03-20 21:33:36 | 355582601 | 20851898 | 1521570809 | sell | 8805.00000000 | 0.00017037 |   1.50010785 |
| 63 | 2018-03-20 21:33:36 | 355582602 | 20851899 | 1521570809 | sell | 8805.00000000 | 0.00017037 |   1.50010785 |
| 64 | 2018-03-20 21:33:36 | 355582604 | 20851900 | 1521570810 | buy  | 8805.27999977 | 0.01230000 | 108.30494399 |
+----+---------------------+-----------+----------+------------+------+---------------+------------+--------------+
15 rows in set (0.00 sec)
 
MariaDB [polo]> SELECT COUNT(1) FROM trade;
+----------+
| COUNT(1) |
+----------+
|     3846 |
+----------+
1 row in set (0.00 sec)
  
 
  
Чтобы экспортировать БД
$ mysqldump -u u -p polo > polo-dump.sql



Импортировать базу пароль: secret (пользователь u)
  
Чтобы импортировать БД
В первый раз нужно ее создать:

$ sudo mysql -u root -p
(Можно задать пароль)

MariaDB [(none)]> create database polo;

Задать учетную запись u для базы polo с паролем secret

MariaDB [(none)]> grant all on polo.* to 'u' identified by 'secret';

MariaDB [(none)]> quit

$ mysql -u u -p polo
 
 
$ mysql -u u -p polo < polo-dump.sql
Некоторые команды делать не нужно: 
 
MariaDB [polo]> select * from trade;
Empty set (0.01 sec)
 
 
MariaDB [polo]> delete from  trade;
Query OK, 13 rows affected (0.02 sec)
 
 
MariaDB [polo]> show tables;
+----------------+
| Tables_in_polo |
+----------------+
| trade          |
+----------------+
1 row in set (0.00 sec)

MariaDB [polo]> drop table trade;
Query OK, 0 rows affected (0.00 sec)


MariaDB [polo]> SHOW TABLES IN polo;
+----------------+
| Tables_in_polo |
+----------------+
| trade          |
+----------------+ 

настройка свечей

import time
import json
import requests
import urllib, http.client
import hmac, hashlib
import mysql.connector
import sys
import os, errno
import calendar
import numpy
import talib

from datetime import datetime

#1518628155 Начало базы 2018-02-14 20:09:15
#print('Начало базы', datetime.fromtimestamp(1518628155))
#Установим дату и время начала тестирования
time_start = (2018, 3, 14, 0, 0, 0, 0, 0, 0) #Время UTC
#timestampstart = time.mktime(time_start) #Локальное время
timestampstart = calendar.timegm(time_start) # время UTC
x=timestampstart
print('Начало тестирования utc ', datetime.utcfromtimestamp(timestampstart))
#Установим дату и время завершения тестирования
time_end = (2018, 3, 15, 0, 0, 0, 0, 0, 0) #Время UTC
#time_end = (2018, 3, 13, 15, 0, 0, 0, 0, 0) #Время UTC
#time_end = (2018, 3, 20, 5, 0, 0, 0, 0, 0) #Время UTC
#timestampend = time.mktime(time_end) #Локальное время
timestampend = calendar.timegm(time_end) # время UTC
print('Заввершение тестирования utc ', datetime.utcfromtimestamp(timestampend))
y=timestampend

PERIOD = 240 #Минут

USE_LOG = True
DEBUG = False # True - выводить отладочную информацию, False - писать как можно меньше
numpy.seterr(all='ignore')


# Свой класс исключений
class ScriptError(Exception):
    pass
class ScriptQuitCondition(Exception):
    pass
    
def is_nan(x):
    return (x is numpy.nan or x != x)


# Получаем данные, необходимые для построения индикаторов
#def get_ticks(pair):
def get_ticks(PER):
    global y
    global x
    #_SQL = """select * from trade"""
    #x=int(time.time())
    #print('y = ',y)
    #print(datetime.fromtimestamp(y))
    pr = PER * 60
    #x= y - pr*50  #Для построения MACD требуется примерно 50 периодов свечей
    #_SQL = """select * from trade where date between 1519318790 and 1519318800; """
    _SQL = """SELECT
                    FLOOR(MIN(`date`)/%s)*%s AS date,
                    SUBSTRING_INDEX(MIN(CONCAT(`date`, '_', id, '_', price)), '_', -1) AS `open`,
                    MAX(price) AS high,
                    MIN(price) AS low,
                    SUBSTRING_INDEX(MAX(CONCAT(`date`, '_', id, '_', price)), '_', -1) AS `close`
              FROM trade
              WHERE date >= %s and date <= %s
              GROUP BY FLOOR(`date`/%s)
              ORDER BY date"""
    #db = mysql.connector.connect(host="localhost", user="u", passwd="secret", db="exmo")
    db = mysql.connector.connect(host="10.8.1.1", user="u", passwd="secret", db="exmo")
    cur = db.cursor()
    cur.execute(_SQL,(pr,pr,x,y,pr))
    sdata=[]
    for item in cur.fetchall():
        sdata.append({'date':int(item[0]),'open':float(item[1]),'high':float(item[2]),'low':float(item[3]),'close':float(item[4])})
    cur.close()
    db.close()
    return sdata

# Выводит всякую информацию на экран, самое важное скидывает в Файл log.txt
def log(*args):
    if USE_LOG:
        l = open("./tester.txt", 'a', encoding='utf-8')
        print(datetime.now(), *args, file=l)
        #print(datetime.fromtimestamp(y+3*60*60), *args, file=l) #Локальное время
        #print(datetime.utcfromtimestamp(y), *args, file=l)  #UTC

        l.close()
    print(datetime.now(),' ', *args)
    #print(datetime.fromtimestamp(y+3*60*60),' ', *args) #Локальное время
    #print(datetime.utcfromtimestamp(y),' ', *args) #UTC

log('свечи PERIOD = ',PERIOD, ' мин')
log('начало запроса', datetime.utcfromtimestamp(x))
log('окончание запроса', datetime.utcfromtimestamp(y))
data=get_ticks(PERIOD)
date=numpy.asarray([int(item['date']) for item in data])
for offset, elem in enumerate(date):
    #print(datetime.fromtimestamp(date[offset]), data[offset]) #Локальное время
    print(datetime.utcfromtimestamp(date[offset]), data[offset]) #UTC

понедельник, 5 марта 2018 г.

Тестирование

import time
import json
import requests
import urllib, http.client
import hmac, hashlib
import mysql.connector
import sys

# Если нет нужных пакетов - читаем тут: https://bablofil.ru/python-indicators/
import numpy
import talib

from datetime import datetime

#Установим дату и время начала тестирования
time_start = (2018, 2, 28, 0, 0, 0, 0, 0, 0)
timestampstart = time.mktime(time_start)
#print(timestampstart)
print('Начало тестирования', datetime.fromtimestamp(timestampstart))
#Установим дату и время завершения тестирования
time_end = (2018, 3, 4, 0, 0, 0, 0, 0, 0)
timestampend = time.mktime(time_end)
#print(timestampend)
print('Завершение тестирования',datetime.fromtimestamp(timestampend))

#y=int(time.time()) - 3600*24*2
y=int(timestampstart)

#print(datetime.fromtimestamp(y))
PERIOD = 5 # Период в минутах для построения свечей краткосрочного MACD
BEAR_PERC = 100  # % что считаем поворотом при медведе (подробности - https://bablofil.ru/macd-python-stock-bot/
BULL_PERC = 0  # % что считаем поворотом при быке (поймать максимум 99)
BUY=True
PROFIT = 1

# ключи API, которые предоставила exmo
#API_KEY = 'K-            кей'
# обратите внимание, что добавлена 'b' перед строкой
#API_SECRET = b'S-секрет'

# Список пар, на которые торгуем
MARKETS = [
    'BTC_USD'
]

CAN_SPEND = 20 # Сколько USD готовы вложить в бай
MARKUP = 0.001 # 0.001 = 0.1% - Какой навар со сделки хотим получать

STOCK_FEE = 0.002 # Какую комиссию берет биржа
#PERIOD = 4 # Период в минутах для построения свечей
ORDER_LIFE_TIME = 0.5 # Через сколько минут отменять неисполненный ордер на покупку 0.5 = 30 сек.

USE_MACD = True # True - оценивать тренд по MACD, False - покупать и продавать невзирая ни на что



API_URL = 'api.exmo.me'
API_VERSION = 'v1'

#USE_LOG = False
USE_LOG = True

DEBUG = False # True - выводить отладочную информацию, False - писать как можно меньше

numpy.seterr(all='ignore')

curr_pair = None

# Свой класс исключений
class ScriptError(Exception):
    pass
class ScriptQuitCondition(Exception):
    pass
    
# все обращения к API проходят через эту функцию
def call_api(api_method, http_method="POST", **kwargs):
    
    payload = {'nonce': int(round(time.time()*1000))}

    if kwargs:
        payload.update(kwargs)
    payload =  urllib.parse.urlencode(payload)

    H = hmac.new(key=API_SECRET, digestmod=hashlib.sha512)
    H.update(payload.encode('utf-8'))
    sign = H.hexdigest()
    
    headers = {"Content-type": "application/x-www-form-urlencoded",
           "Key":API_KEY,
           "Sign":sign}
    conn = http.client.HTTPSConnection(API_URL, timeout=90)
    conn.request(http_method, "/"+API_VERSION + "/" + api_method, payload, headers)
    response = conn.getresponse().read()
    
    conn.close()

    try:
        obj = json.loads(response.decode('utf-8'))

        if 'error' in obj and obj['error']:
            raise ScriptError(obj['error'])
        return obj
    except json.decoder.JSONDecodeError:
        raise ScriptError('Ошибка анализа возвращаемых данных, получена строка', response)

# Получаем с биржи данные, необходимые для построения индикаторов
#def get_ticks(pair):
def get_ticks(pair, PER):
    global y
    #print('PER =', PER)
    #resource = requests.get('https://api.exmo.me/v1/trades/?pair=%s&limit=10000' % pair)
    #data = json.loads(resource.text)
    #_SQL = """select * from trade"""
    #x=int(time.time())
    print(datetime.fromtimestamp(y))
    pr = PER * 60
    x= y - pr*100
    #_SQL = """select * from trade where date between 1519318790 and 1519318800; """
    _SQL = """SELECT
                    FLOOR(MIN(`date`)/%s)*%s AS date,
                    SUBSTRING_INDEX(MIN(CONCAT(`date`, '_', id, '_', price)), '_', -1) AS `open`,
                    MAX(price) AS high,
                    MIN(price) AS low,
                    SUBSTRING_INDEX(MAX(CONCAT(`date`, '_', id, '_', price)), '_', -1) AS `close`
              FROM trade
              WHERE date >= %s and date <= %s
              GROUP BY FLOOR(`date`/%s)
              ORDER BY date"""
    db = mysql.connector.connect(host="localhost", user="u", passwd="secret", db="exmo")
    cur = db.cursor()
    cur.execute(_SQL,(pr,pr,x,y,pr))
    chart_data = {} # сформируем словарь с ценой закрытия по PERIOD минут
    #s=int(float(data[pair][1]['date'])/(PERIOD*60))*(PERIOD*60) #Время последней свечи, которая все время  меняется
    for item in cur.fetchall():
        d = item[0] # Округляем время сделки до PERIOD минут
        if not d in chart_data:
            chart_data[d] = {'open':0, 'close':0, 'high':0, 'low':0}
        chart_data[d]['close'] = float(item[4])
        chart_data[d]['open'] = float(item[1])
        chart_data[d]['high'] = float(item[2])
        chart_data[d]['low'] = float(item[3])
    cur.close()
    db.close()
    return chart_data
# С помощью MACD делаем вывод о целесообразности торговли в данный момент (https://bablofil.ru/macd-python-stock-bot/)

def get_macd_advice(chart_data):  
    quotes = {}
    quotes['open']=numpy.asarray([chart_data[item]['open'] for item in sorted(chart_data)])
    quotes['close']=numpy.asarray([chart_data[item]['close'] for item in sorted(chart_data)])
    quotes['high']=numpy.asarray([chart_data[item]['high'] for item in sorted(chart_data)])
    quotes['low']=numpy.asarray([chart_data[item]['low'] for item in sorted(chart_data)])
    #print(quotes['close'][-1])

    macd, macdsignal, macdhist = talib.MACD(quotes['close'], fastperiod=12, slowperiod=26, signalperiod=9)
    slowk, slowd = talib.STOCH(quotes['high'], quotes['low'], quotes['close'], fastk_period=21, slowk_period=1, slowk_matype=0, slowd_period=3, slowd_matype=0)
    #macd, macdsignal, macdhist = talib.MACD(numpy.asarray([chart_data[item] for item in sorted(chart_data)]), fastperiod=12, slowperiod=26, signalperiod=9)
    #real  = talib.RSI(numpy.asarray([chart_data[item] for item in sorted(chart_data)]), timeperiod=14)
    real = talib.AROONOSC(quotes['high'], quotes['low'], timeperiod=14)
    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)
    trand = 'BULL' if macd[-1] > macdsignal[-1] else 'BEAR'
    max_v = 0
    growing = False
    for offset, elem in enumerate(macdhist):
        growing = 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]): # восходящий тренд
            v = 1
            growing = True
            mc = macd[offset]
        else:
            v = 0
        if offset in idx and not numpy.isnan(elem):
            # тренд изменился
            max_v = curr_v = 0 # обнуляем пик спреда между линиями
        #hist_data.append(v*1000)
    #hist_data2 = []
    for offset, elem in enumerate(slowk):
        a=20
        p_a=float(slowk[offset-1])
        p_b=float(slowd[offset-1])
        p_c=float(slowd[offset])
        p_d=float(slowk[offset])
        try:
            if (p_a<a and p_b<a and p_c<a and p_d<a) and (p_a==p_b and p_a==p_d):
                av_point=a/2
            elif (p_a>100-a and p_b>100-a and p_c>100-a and p_d>100-a) and (p_a==p_b and p_a==p_d):
                av_point=100-a/2
            else:
                av_point=((p_c-p_b)*(p_a-p_b)/((p_c-p_b)+(p_a-p_d)))+p_b
        except:
            print('деление на 0?')
        v=0
        if (slowk[offset-1] < slowd[offset-1] and slowk[offset] >= slowd[offset] and av_point<a):
            v = -1 # Покупать!
        if (slowk[offset-1] > slowd[offset-1] and slowk[offset] <= slowd[offset] and av_point>80):
            #activity_time = True
            v= 1 # Продовать!
        #hist_data2.append(v)
    #return ({'curr':(macd[-1] -  macdsignal[-1]),'macd':mc,  'trand':trand, 'growing':growing,'stoch':v, 'close':quotes['close'][-1],'rsi':real[-1]})
    return ({'trand':trand, 'growing':growing,'stoch':v, 'close':quotes['close'][-1]})
# Выводит всякую информацию на экран, самое важное скидывает в Файл log.txt
def log(*args):
    
    if USE_LOG:
        l = open("./tester.txt", 'a', encoding='utf-8')
        #print(datetime.now(), *args, file=l)
        print(datetime.fromtimestamp(y), *args, file=l)
        l.close()
    #print(datetime.now(),' ', *args)
    print(datetime.fromtimestamp(y),' ', *args)

# Ф-ция для создания ордера на покупку
def create_buy(pair):
    #global USE_LOG
    #USE_LOG = True
    log(pair, "Создаем ордер на покупку")
    #USE_LOG = False  
    
# Ф-ция для создания ордера на продажу
def create_sell(pair):
    #global USE_LOG
    #USE_LOG = True
    log(pair, "Создаем ордер на продажу")
# Ф-ция для определения падения  цены покупки
def good_price(pair): # Возвращает True при  цене продажи > 1.005 цены покупки
    drop = True
    return(drop)
# Бесконечный цикл процесса - основная логика
while True:
    try:
        for pair in MARKETS: # Проходим по каждой паре из списка в начале\           
            try:
                macd_advice = get_macd_advice(chart_data=get_ticks(pair,PERIOD))
                print("Ситуация на рынке:", macd_advice)
                if BUY:
                    #if macd_advice['growing'] and macd_advice['stoch']==-1:
                    if macd_advice['growing']:
                        BUY = False
                        log(pair, "Ситуация на рынке:", macd_advice)
                        PRICE = macd_advice['close']
                        log(pair, "цена покупки:", PRICE)
                        PRICE1 = PRICE *1.005
                        #log(pair, "Продажа не дешевле:", PRICE1)
                        log(pair, "Покупаем")
                        log(pair, "-------------------------------------------")
                else:
                #if False:
                    #if macd_advice['growing'] and macd_advice['stoch']==1:
                    if not macd_advice['growing']:
                        if macd_advice['close'] >= PRICE1:
                            log(pair, "Ситуация на рынке:", macd_advice)
                            #log(pair, "Продажа не дешевле:", PRICE1)
                            PRICE2 = macd_advice['close']     
                            log(pair, "Цена продажи:", PRICE2)
                            BUY =  True
                            PROF = PRICE2/PRICE - 0.004
                            log(pair, "Профит от продажи:", PROF)
                            PROFIT = PROFIT*PROF
                            log(pair, "Профит от начала:", PROFIT)
                            log(pair, "Продаем")
                            log(pair, "-------------------------------------------")
                        #else:
                            #log(pair, "цена покупки:", PRICE)
                            #log(pair, "Ситуация на рынке:", macd_advice)
                            #log(pair, "не продаем дешевле!")
            except ScriptError as e:
                    print(e)
            except ScriptQuitCondition as e:
                print(e)
            except Exception as e:
                print("!!!!",e)
        #time.sleep(1)
        y=y+10 # Прибавляем 10 с.
        if y > timestampend:
            log(pair, "Завершение тестирования!")
            sys.exit()
    except Exception as e:
        print(e)

воскресенье, 4 марта 2018 г.

Импорт и экспорт баз данных MySQL и MariaDB

Импорт и экспорт баз данных MySQL и MariaDB
  
Для ubuntu 16.04 
 
$ sudo apt update
$ sudo apt upgrade 
$ sudo apt install python3-mysql.connector 
 
Установка  MariaDB:
$ sudo apt install mariadb-server -y
 
$ sudo mysql -u root -p
(Можно задать пароль) 
 
Создать базу: 
MariaDB [(none)]> create database exmo; 
MariaDB [(none)]> quit 
 
Импортировать базу пароль: secret (пользователь u)
 
$ mysql -u u -p exmo < data-dump.sql 
 
Все можно работать! 
--------------------------------------------------------------------------------- 
Чтобы экспортировать БД
$ mysqldump -u u -p exmo > data-dump.sql
 

пятница, 23 февраля 2018 г.

Правим def get_ticks()

def get_ticks(pair, PER):
    print('PER =', PER)
    #_SQL = """select * from trade"""
    x=int(time.time())
    pr = PER * 60
    x= x - pr*100
    _SQL = """SELECT
                    FLOOR(MIN(`date`)/%s)*%s AS date,
                    SUBSTRING_INDEX(MIN(CONCAT(`date`, '_', id, '_', price)), '_', -1) AS `open`,
                    MAX(price) AS high,
                    MIN(price) AS low,
                    SUBSTRING_INDEX(MAX(CONCAT(`date`, '_', id, '_', price)), '_', -1) AS `close`
              FROM trade
              WHERE date >= %s
              GROUP BY FLOOR(`date`/%s)
              ORDER BY date"""
    db = mysql.connector.connect(host="localhost", user="u", passwd="secret", db="exmo")
    cur = db.cursor()
    cur.execute(_SQL,(pr,pr,x,pr))
    chart_data = {} # сформируем словарь с ценой закрытия по PERIOD минут
    for item in cur.fetchall():
        d = item[0] # Округляем время сделки до PERIOD минут
        if not d in chart_data:
            chart_data[d] = {'open':0, 'close':0, 'high':0, 'low':0}
        chart_data[d]['close'] = float(item[4])
        chart_data[d]['open'] = float(item[1])
        chart_data[d]['high'] = float(item[2])
        chart_data[d]['low'] = float(item[3])
    cur.close()
    db.close()
    return chart_data
------------------------------------------------------------------------------------------------------------------------
Поясним как работает:
SUBSTRING_INDEX(MAX(CONCAT(`date`, '_', id, '_', price)), '_', -1) AS `close`



Мы замешиваем date, id, price:
1519478976_57723762_1090.00000000
Из записей с одинаковым временем берем с большим id ( функция MAX())
Далее выделяем цену функцией SUBSTRING_INDEX() - 1090.00000000

Python индикатор MACD

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
import mysql.connector

PERIOD = 120 # Период в минутах для построения свечей

BEAR_PERC = 100
BULL_PERC =  0
PAIR = 'BTC_USD'

fig, ax = plt.subplots(3, sharex=True)
fig.comment = plt.figtext(.7,.05, '')

db = mysql.connector.connect(host="localhost", user="u", passwd="secret", db="exmo")
#db = mysql.connector.connect(host="10.8.1.1", user="u", passwd="secret", db="exmo")
cur = db.cursor()

def update_graph(interval):
    x=int(time.time())
    per = PERIOD * 60
    x= x - per*100
    _SQL = """SELECT
                    FLOOR(MIN(`date`)/%s)*%s AS date,
                    SUBSTRING_INDEX(MIN(CONCAT(`date`, '_', id, '_', price)), '_', -1) AS `open`,
                    MAX(price) AS high,
                    MIN(price) AS low,
                    SUBSTRING_INDEX(MAX(CONCAT(`date`, '_', id, '_', price)), '_', -1) AS `close`
              FROM trade              WHERE date >= %s
              GROUP BY FLOOR(`date`/%s)
              ORDER BY date"""
    cur.execute(_SQL,(per,per,x,per))
    chart_data = {} # сформируем словарь с ценой закрытия по PERIOD минут
    for item in cur.fetchall():
        d = item[0] # Округляем время сделки до PERIOD минут
        if not d in chart_data:
            chart_data[d] = {'open':0, 'close':0, 'high':0, 'low':0}
        chart_data[d]['close'] = float(item[4])
        chart_data[d]['open'] = float(item[1])
        chart_data[d]['high'] = float(item[2])
        chart_data[d]['low'] = float(item[3])
    quotes = {}
    quotes['open']=numpy.asarray([chart_data[item]['open'] for item in sorted(chart_data)])
    quotes['close']=numpy.asarray([chart_data[item]['close'] for item in sorted(chart_data)])
    quotes['high']=numpy.asarray([chart_data[item]['high'] for item in sorted(chart_data)])
    quotes['low']=numpy.asarray([chart_data[item]['low'] for item in sorted(chart_data)])
    xdate=[datetime.fromtimestamp(item) for item in sorted(chart_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))
    ax[0].grid(True)
    ax[0].minorticks_on()
    # Customize the major grid
    ax[0].grid(which='major', linestyle='-', linewidth='0.5', color='red')
    # Customize the minor grid
    ax[0].grid(which='minor', linestyle=':', linewidth='0.5', color='black')
    candlestick2_ohlc(ax[0], quotes['open'],quotes['high'],quotes['low'],quotes['close'],width=0.6)
    fig.autofmt_xdate()
    fig.tight_layout()
    macd, macdsignal, macdhist = talib.MACD(quotes['close'], fastperiod=12, slowperiod=26, signalperiod=9)
    #macd, macdsignal, macdhist = talib.MACDFIX(quotes['close'], signalperiod=9)
    #real = talib.RSI(quotes['close'], timeperiod=14)
    #real = talib.AROONOSC(quotes['high'], quotes['low'], timeperiod=14)
    ax[1].clear()
    ax[1].grid(True)
    ax[1].minorticks_on()
    # Customize the major grid
    ax[1].grid(which='major', linestyle='-', linewidth='0.5', color='red')
    # Customize the minor grid
    ax[1].grid(which='minor', linestyle=':', linewidth='0.5', color='black')
    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')
    hist_data = []
    hist_data1 = []
    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)) ):
        #if       (   (macd[offset] - macdsignal[offset] > 0) # восходящий тренд
                #):
            #v = 1
            v=curr_v
            activity_time = True
        else:
            v = 0
            #v = -1
        hist_data.append(v)
        v1 = 0
        if curr_v < 0:
            v1 = curr_v
        hist_data1.append(v1)
        if offset in idx and not numpy.isnan(elem):
            # тренд изменился
            max_v = curr_v = 0 # обнуляем пик спреда между линиями
    ax[2].clear()
    ax[2].grid(True)
    ax[2].minorticks_on()
    # Customize the major grid
    ax[2].grid(which='major', linestyle='-', linewidth='0.5', color='red')
    # Customize the minor grid
    ax[2].grid(which='minor', linestyle=':', linewidth='0.5', color='black')
    #ax[2].plot(real, color="y")
    ax[2].fill_between([x for x in range(len(macdhist))], 0, hist_data, facecolor='green', interpolate=True)
    ax[2].fill_between([x for x in range(len(macdhist))], 0, hist_data1, facecolor='red', interpolate=True)
    plt.gcf().texts.remove(fig.comment)
    fig.comment = plt.figtext(.6,.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})

ani = animation.FuncAnimation(fig, update_graph, interval=1000)
plt.show()

Python добавление данных mysql

import numpy
#import talib
import requests
import json
import time
import mysql.connector
#from matplotlib.finance import candlestick2_ohlc
#i#mport matplotlib.animation as animation
#import matplotlib.pyplot as plt
#import matplotlib.ticker as ticker
from datetime import datetime


def update_mysql():
    PAIR = 'BTC_USD'
    db = mysql.connector.connect(host="localhost", user="u", passwd="secret", db="exmo")
    cur = db.cursor()
    resource = requests.get('https://api.exmo.com/v1/trades/?pair=%s&limit=500' % PAIR)
    #resource = requests.get('https://api.exmo.com/v1/trades/?pair=%s&limit=10000' % PAIR)
    data = json.loads(resource.text)
    #print(data[PAIR][1])
    chart_data = {} # сформируем словарь с ценой закрытия по PERIOD минут
    #print(data[PAIR][1]['date'])
    #print(int(float(data[PAIR][1]['date'])/(PERIOD*60))*(PERIOD*60))
    #print('-----------------------------')
    for item in reversed(data[PAIR]):
        _SQL = """insert ignore into trade
                  (trade_id, type, amount, quantity, date, price)
                  values
                  (%s,%s,%s,%s,%s,%s)"""
        cur.execute(_SQL, (item['trade_id'],item['type'],item['amount'],item['quantity'],item['date'],item['price']))
        db.commit()
    #cur.close()
    #db.close()
   
    FLAG = False
    if FLAG:
        _SQL = """select * from trade"""
        cur.execute(_SQL)
        for row in cur.fetchall():
            print(row)
    db.commit()
    cur.close()
    db.close()
    return()
# Бесконечный цикл процесса - основная логика
while True:
    try:
        update_mysql()
        time.sleep(1)
        print('работаем!')
    except Exception as e:
        print(e)

В обновлялке стоит лимит 500 записей, поставьте 10000 что бы не было пропусков, а затем поставьте обратно 500.