import pymongo
import pandas as pd
from pandas import Series,DataFrame
import talib
from talib import MA_Type
import numpy
import numpy as np
import warnings
warnings.filterwarnings("ignore")
from sklearn.metrics import classification_report
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score # 准确率
import joblib

class Machinelearn:
"""
"""

def __init__(self, load_num, percent, interval, symbol):
    """"""
    self.load_num = load_num
    self.percent = percent
    self.interval = interval
    self.symbol = symbol

    self.df = self.init_mongo()
    self.init_df(self.df)
    self.train_df(self.df)


def init_mongo(self):
    connect = pymongo.MongoClient('127.0.0.1:27017')  # 连接本地MongoDB服务器/127.0.0.1
    db = connect.vnpy  # 连接(创建)mongo_demo数据库
    employees = db.db_bar_data  # 连接(创建)employe
    cursor = employees.find(
        {'interval': self.interval, 'symbol': self.symbol},  # 1m 1h d
        {'_id': 0, 'datetime': 1, 'open_price': 1, "close_price": 1, "high_price": 1, "low_price": 1, "volume": 1}
    )
    df = pd.DataFrame(list(cursor))
    return df

def mark_price(self,max_price, min_price, close_price):
    if max_price == close_price:
        return 1
    elif min_price == close_price:
        return -1
    else:
        return 0

def w_file(self, file_content, filepath="demo.json"):
    fp = open(str(filepath), "a+")
    try:
        fp.write(str(file_content) + "\n")
    except:
        pass
    fp.close()

def init_df(self,df):
    #df = df[df.apply(lambda x: x["volume"] != 0.0, axis=1)]
    #print(df)
    """
    #1
    df['max_price'] = df['high_price'].rolling(window=10,center=True).max()
    df['min_price'] = df['low_price'].rolling(window=10,center=True).min()
    def mm(max_price,high_price,min_price,low_price):
        if max_price == high_price:
            return 1
        elif min_price ==low_price:
            return -1
        else:
            return 0
    df['mm'] = df.apply(lambda x: mm(x["max_price"],x["high_price"],x["min_price"],x['low_price']), axis=1)
    """
    # 2
    df['max_price'] = df['close_price'].rolling(window=self.load_num, center=True).max()
    df['min_price'] = df['close_price'].rolling(window=self.load_num, center=True).min()
    df['mm'] = df.apply(lambda x: self.mark_price(x["max_price"], x["min_price"], x['close_price']), axis=1)

    # SMA
    df['MA10'] = talib.MA(df['close_price'], 10)
    df['MA20'] = talib.MA(df['close_price'], 20)
    df['MA30'] = talib.MA(df['close_price'], 30)
    df['MA60'] = talib.MA(df['close_price'], 60)
    # df['SMA120'] =  talib.SMA(df['close_price'], 120)
    # df['SMA256'] =  talib.SMA(df['close_price'], 256)

    # overlap studies重叠的指标

    # BBANDS               Bollinger Bands
    # 函数名:BBANDS
    # 名称: 布林线指标
    # 简介:其利用统计原理,求出股价的标准差及其信赖区间,从而确定股价的波动范围及未来走势,利用波带显示股价的安全高低价位,因而也被称为布林带。
    # 分析和应用: 百度百科 同花顺学院
    # upperband, middleband, lowerband = BBANDS(close, timeperiod=5, nbdevup=2, nbdevdn=2, matype=0)

    df["BBANDS_upper"], df["BBANDS_middle"], df["BBANDS_lower"] = talib.BBANDS(
        df['close_price'], matype=MA_Type.T3)

    # DEMA - Double Exponential Moving Average 双移动平均线
    # 函数名:DEMA
    # 名称: 双移动平均线
    # 简介:两条移动平均线来产生趋势信号,较长期者用来识别趋势,较短期者用来选择时机。正是两条平均线及价格三者的相互作用,才共同产生了趋势信号。
    # real = DEMA(close, timeperiod=30)
    df["DEMA"] = talib.DEMA(df['close_price'], timeperiod=30)
    # MA - Moving average 移动平均线
    # 函数名:MA
    # 名称: 移动平均线
    # 简介:移动平均线,Moving Average,简称MA,原本的意思是移动平均,由于我们将其制作成线形,所以一般称之为移动平均线,简称均线。它是将某一段时间的收盘价之和除以该周期。 比如日线MA5指5天内的收盘价除以5 。
    # real = MA(close, timeperiod=30, matype=0)
    df["MA"] = talib.MA(df['close_price'], timeperiod=30, matype=0)
    # EMA和MACD
    # 调用talib计算6日指数移动平均线的值
    df['EMA12'] = talib.EMA(df['close_price'], timeperiod=6)
    df['EMA26'] = talib.EMA(df['close_price'], timeperiod=12)
    # KAMA - Kaufman Adaptive Moving Average 考夫曼的自适应移动平均线
    # 函数名:KAMA
    # 名称: 考夫曼的自适应移动平均线
    # 简介:短期均线贴近价格走势,灵敏度高,但会有很多噪声,产生虚假信号;长期均线在判断趋势上一般比较准确 ,但是长期均线有着严重滞后的问题。我们想得到这样的均线,当价格沿一个方向快速移动时,短期的移动 平均线是最合适的;当价格在横盘的过程中,长期移动平均线是合适的。
    # NOTE: The KAMA function has an unstable period.
    df["KAMA"] = talib.KAMA(df['close_price'], timeperiod=30)

    # SMA (简单移动平均线)(参数1:收盘价序列,参数2:时间周期(均线的计算长度 即 几日均线))
    # SAREXT - Parabolic SAR - Extended
    # real = SAREXT(high, low, startvalue=0, offsetonreverse=0, accelerationinitlong=0, accelerationlong=0, accelerationmaxlong=0, accelerationinitshort=0, accelerationshort=0, accelerationmaxshort=0)
    # SMA - Simple Moving Average 简单移动平均线
    # 函数名:SMA
    # 名称: 简单移动平均线
    # 简介:移动平均线,Moving Average,简称MA,原本的意思是移动平均,由于我们将其制作成线形,所以一般称之为移动平均线,简称均线。它是将某一段时间的收盘价之和除以该周期。 比如日线MA5指5天内的收盘价除以5 。
    # 百度百科 同花顺学院
    # real = SMA(close, timeperiod=30)
    df['SMA'] = talib.SMA(df['close_price'], timeperiod=30)
    # MIDPRICE - Midpoint Price over period
    df["MIDPOINT"] = talib.MIDPOINT(df['close_price'], timeperiod=14)
    # SAR - Parabolic SAR 抛物线指标
    # 函数名:SAR
    # 名称: 抛物线指标
    # 简介:抛物线转向也称停损点转向,是利用抛物线方式,随时调整停损点位置以观察买卖点。由于停损点(又称转向点SAR)以弧形的方式移动,故称之为抛物线转向指标 。
    # real = SAR(high, low, acceleration=0, maximum=0)
    df["SAR"] = talib.SAR(df['high_price'], df['low_price'], acceleration=0, maximum=0)
    # T3 - Triple Exponential Moving Average (T3) 三重指数移动平均线
    # 函数名:T3
    # 名称:三重指数移动平均线
    # 简介:TRIX长线操作时采用本指标的讯号,长时间按照本指标讯号交易,获利百分比大于损失百分比,利润相当可观。 比如日线MA5指5天内的收盘价除以5 。
    # NOTE: The T3 function has an unstable period
    # real = T3(close, timeperiod=5, vfactor=0)
    df["T3"] = talib.T3(df['close_price'], timeperiod=5, vfactor=0)
    # TEMA - Triple Exponential Moving Average
    # 函数名:TEMA(T3 区别?) 名称:三重指数移动平均线
    # real = TEMA(close, timeperiod=30)
    df["TEMA"] = talib.TEMA(df['close_price'], timeperiod=30)
    # MIDPRICE - Midpoint Price over period
    # real = MIDPRICE(high, low, timeperiod=14)
    df["MIDPRICE"] = talib.MIDPRICE(df['high_price'], df['low_price'], timeperiod=14)
    # TRIMA - Triangular Moving Average
    df["TRIMA"] = talib.TRIMA(df['close_price'], timeperiod=30)
    # df["SAREXT"]=talib.SAREXT(high_p, low_p, maximum=0)
    # SAREXT - Parabolic SAR - Extended
    df["SAREXT"] = talib.SAREXT(df['high_price'], df['low_price'], startvalue=0, offsetonreverse=0,
                                accelerationinitlong=0, accelerationlong=0, accelerationmaxlong=0,
                                accelerationinitshort=0, accelerationshort=0, accelerationmaxshort=0)
    # WMA - Weighted Moving Average 移动加权平均法
    # 函数名:WMA
    # 名称:加权移动平均线
    # 简介:移动加权平均法是指以每次进货的成本加上原有库存存货的成本,除以每次进货数量与原有库存存货的数量之和,据以计算加权平均单位成本,以此为基础计算当月发出存货的成本和期末存货的成本的一种方法。
    df["WMA"] = talib.WMA(df['close_price'], timeperiod=30)
    # Volatility Indicator Functions 波动率指标函数
    # ATR - Average True Range
    # 函数名:ATR
    # 名称:真实波动幅度均值
    # 简介:真实波动幅度均值(ATR)是 以 N 天的指数移动平均数平均後的交易波动幅度。 计算公式:一天的交易幅度只是单纯地 最大值 - 最小值。
    # 而真实波动幅度则包含昨天的收盘价,若其在今天的幅度之外:
    # 真实波动幅度 = max(最大值,昨日收盘价) − min(最小值,昨日收盘价) 真实波动幅度均值便是「真实波动幅度」的 N 日 指数移动平均数。
    # 特性::
    # 波动幅度的概念表示可以显示出交易者的期望和热情。
    # 大幅的或增加中的波动幅度表示交易者在当天可能准备持续买进或卖出股票。
    # 波动幅度的减少则表示交易者对股市没有太大的兴趣。
    # NOTE: The ATR function has an unstable period.
    # real = ATR(high, low, close, timeperiod=14)
    # ATR(平均真实波幅)(参数1:最高价序列,参数2:最低价序列,参数3:收盘价序列,参数4:时间周期)
    df["ATR"] = talib.ATR(df['high_price'], df['low_price'], df['close_price'], timeperiod=14)
    # NATR - Normalized Average True Range
    # 函数名:NATR
    # 名称:归一化波动幅度均值
    # 简介:归一化波动幅度均值(NATR)是
    # NOTE: The NATR function has an unstable period.
    # real = NATR(high, low, close, timeperiod=14)
    df["NATR"] = talib.NATR(df['high_price'], df['low_price'], df['close_price'], timeperiod=14)
    # TRANGE - True Range
    # 函数名:TRANGE
    # 名称:真正的范围
    # real = TRANGE(high, low, close)
    df["TRANGE"] = talib.TRANGE(df['high_price'], df['low_price'], df['close_price'])
    # Volume Indicators 成交量指标

    # AD - Chaikin A/D Line 量价指标
    # 函数名:AD
    # 名称:Chaikin A/D Line 累积/派发线(Accumulation/Distribution Line)
    # 简介:Marc Chaikin提出的一种平衡交易量指标,以当日的收盘价位来估算成交流量,用于估定一段时间内该证券累积的资金流量。
    # 计算公式:
    # 多空对比 = [(收盘价- 最低价) - (最高价 - 收盘价)] / (最高价 - 最低价)
    # 若最高价等于最低价: 多空对比 = (收盘价 / 昨收盘) - 1
    # 研判:
    # 1、A/D测量资金流向,向上的A/D表明买方占优势,而向下的A/D表明卖方占优势
    # 2、A/D与价格的背离可视为买卖信号,即底背离考虑买入,顶背离考虑卖出
    # 3、应当注意A/D忽略了缺口的影响,事实上,跳空缺口的意义是不能轻易忽略的
    # A/D指标无需设置参数,但在应用时,可结合指标的均线进行分析
    # real = AD(high, low, close, volume)
    df["AD"] = talib.AD(df['high_price'], df['low_price'], df['close_price'], df['volume'])
    # ADOSC - Chaikin A/D Oscillator
    # 函数名:ADOSC
    # 名称:Chaikin A/D Oscillator Chaikin震荡指标
    # 简介:将资金流动情况与价格行为相对比,检测市场中资金流入和流出的情况
    # 计算公式:fastperiod A/D - slowperiod A/D
    # 研判:
    # 1、交易信号是背离:看涨背离做多,看跌背离做空
    # 2、股价与90天移动平均结合,与其他指标结合
    # 3、由正变负卖出,由负变正买进
    # real = ADOSC(high, low, close, volume, fastperiod=3, slowperiod=10)
    df["ADOSC"] = talib.ADOSC(df['high_price'], df['low_price'], df['close_price'], df['volume'], fastperiod=3,
                              slowperiod=10)
    # OBV - On Balance Volume
    # 函数名:OBV
    # 名称:On Balance Volume 能量潮
    # 简介:Joe Granville提出,通过统计成交量变动的趋势推测股价趋势
    # 计算公式:以某日为基期,逐日累计每日上市股票总成交量,若隔日指数或股票上涨 ,则基期OBV加上本日成交量为本日OBV。隔日指数或股票下跌, 则基期OBV减去本日成交量为本日OBV
    # 研判:
    # 1、以“N”字型为波动单位,一浪高于一浪称“上升潮”,下跌称“跌潮”;上升潮买进,跌潮卖出
    # 2、须配合K线图走势
    # 3、用多空比率净额法进行修正,但不知TA-Lib采用哪种方法
    # 计算公式: 多空比率净额= [(收盘价-最低价)-(最高价-收盘价)] ÷( 最高价-最低价)×成交量
    # real = OBV(close, volume)
    df["OBV"] = talib.OBV(df['close_price'], df['volume'])
    # Cycle Indicator Functions
    # HT_DCPERIOD - Hilbert Transform - Dominant Cycle Period
    # 函数名:HT_DCPERIOD
    # 名称: 希尔伯特变换-主导周期
    # 简介:将价格作为信息信号,计算价格处在的周期的位置,作为择时的依据。
    # NOTE: The HT_DCPERIOD function has an unstable period.
    # real = HT_DCPERIOD(close)
    df["HT_DCPERIOD"] = talib.HT_DCPERIOD(df['close_price'])
    # HT_DCPHASE - Hilbert Transform - Dominant Cycle Phase
    # 函数名:HT_DCPHASE
    # 名称: 希尔伯特变换-主导循环阶段
    # NOTE: The HT_DCPHASE function has an unstable period.
    # real = HT_DCPHASE(close)
    df["HT_DCPHASE"] = talib.HT_DCPHASE(df['close_price'])

    # HT_PHASOR - Hilbert Transform - Phasor Components
    # 函数名:HT_DCPHASE
    # 名称: 希尔伯特变换-希尔伯特变换相量分量
    # NOTE: The HT_PHASOR function has an unstable period.
    # inphase, quadrature = HT_PHASOR(close)
    df["HT_PHASOR_inphase"], df["HT_PHASOR_quadrature"] = talib.HT_PHASOR(df['close_price'])
    # HT_SINE - Hilbert Transform - SineWave
    # 函数名:HT_DCPHASE
    # 名称: 希尔伯特变换-正弦波 NOTE: The HT_SINE function has an unstable period.
    # sine, leadsine = HT_SINE(close)
    df["HT_SINE_sine"], df["HT_SINE_leadsine"] = talib.HT_SINE(df['close_price'])
    # HT_TRENDMODE - Hilbert Transform - Trend vs Cycle Mode
    # 函数名:HT_DCPHASE
    # 名称: 希尔伯特变换-趋势与周期模式
    # NOTE: The HT_TRENDMODE function has an unstable period.
    # integer = HT_TRENDMODE(close)
    df["HT_TRENDMODE"] = talib.HT_TRENDMODE(df['close_price'])
    # Price Transform Functions
    # $GPRICE - Average Price
    # 函数名:$GPRICE
    # 名称:平均价格函数
    # real = $GPRICE(open, high, low, close)
    df["$GPRICE"] = talib.$GPRICE(df['open_price'], df['high_price'], df['low_price'], df['close_price'])
    # MEDPRICE - Median Price
    # 函数名:MEDPRICE
    # 名称:中位数价格
    # real = MEDPRICE(high, low)
    df["MEDPRICE"] = talib.MEDPRICE(df['high_price'], df['low_price'])

    # TYPPRICE - Typical Price
    # 函数名:TYPPRICE
    # 名称:代表性价格
    # real = TYPPRICE(high, low, close)
    df["TYPPRICE"] = talib.TYPPRICE(df['high_price'], df['low_price'], df['close_price'])

    # WCLPRICE - Weighted Close Price
    # 函数名:WCLPRICE
    # 名称:加权收盘价
    # real = WCLPRICE(high, low, close)
    df["WCLPRICE"] = talib.WCLPRICE(df['high_price'], df['low_price'], df['close_price'])
    # Momentum Indicator Functions
    # ADX - Average Directional Movement Index
    # 函数名:ADX
    # 名称:平均趋向指数
    # 简介:使用ADX指标,指标判断盘整、振荡和单边趋势。
    # 公式:
    # 一、先决定股价趋势(Directional Movement,DM)是上涨或下跌:
    # “所谓DM值,今日股价波动幅度大于昨日股价波动幅部分的最大值,可能是创高价的部分或创低价的部分;如果今日股价波动幅度较前一日小,则DM = 0。”
    # 若股价高点持续走高,为上涨趋势,记作 +DM。
    # 若为下跌趋势,记作 -DM。-DM的负号(–)是表示反向趋势(下跌),并非数值为负数。
    # 其他状况:DM = 0。
    # 二、寻找股价的真实波幅(True Range,TR):
    # 所谓真实波幅(TR)是以最高价,最低价,及前一日收盘价三个价格做比较,求出当日股价波动的最大幅度。
    # 三、趋势方向需经由一段时间来观察,研判上才有意义。一般以14天为指标的观察周期:
    # 先计算出 +DM、–DM及TR的14日算术平均数,得到 +DM14、–DM14及TR14三组数据作为起始值,再计算各自的移动平均值(EMA)。
    #     +DI14 = +DM/TR14*100
    #     -DI14 = +DM/TR14*100
    #     DX = |(+DI14)-(-DI14)| / |(+DI14)+(-DI14)|
    #     DX运算结果取其绝对值,再将DX作移动平均,得到ADX。
    # 特点:
    # ADX无法告诉你趋势的发展方向。
    # 如果趋势存在,ADX可以衡量趋势的强度。不论上升趋势或下降趋势,ADX看起来都一样。
    # ADX的读数越大,趋势越明显。衡量趋势强度时,需要比较几天的ADX 读数,观察ADX究竟是上升或下降。ADX读数上升,代表趋势转强;如果ADX读数下降,意味着趋势转弱。
    # 当ADX曲线向上攀升,趋势越来越强,应该会持续发展。如果ADX曲线下滑,代表趋势开始转弱,反转的可能性增加。
    # 单就ADX本身来说,由于指标落后价格走势,所以算不上是很好的指标,不适合单就ADX进行操作。可是,如果与其他指标配合运用,ADX可以确认市场是否存在趋势,并衡量趋势的强度。
    # 指标应用:
    # +DI与–DI表示多空相反的二个动向,当据此绘出的两条曲线彼此纠结相缠时,代表上涨力道与下跌力道相当,多空势均力敌。当 +DI与–DI彼此穿越时,由下往上的一方其力道开始压过由上往下的另一方,此时出现买卖讯号。
    # ADX可作为趋势行情的判断依据,当行情明显朝多空任一方向进行时,ADX数值都会显著上升,趋势走强。若行情呈现盘整格局时,ADX会低于 +DI与–DI二条线。若ADX数值低于20,则不论DI表现如何,均显示市场没有明显趋势。
    # ADX持续偏高时,代表“超买”(Overbought)或“超卖”(Oversold)的现象,行情反转的机会将增加,此时则不适宜顺势操作。当ADX数值从上升趋势转为下跌时,则代表行情即将反转;若ADX数值由下跌趋势转为上升时,行情将止跌回升。
    # 总言之,DMI指标包含4条线:+DI、-DI、ADX和ADXR。+DI代表买盘的强度、-DI代表卖盘的强度;ADX代表趋势的强度、ADXR则为ADX的移动平均。
    # NOTE: The ADX function has an unstable period.
    # real = ADX(high, low, close, timeperiod=14)
    df["ADX"] = talib.ADX(df['high_price'], df['low_price'], df['close_price'], timeperiod=14)
    # ADXR- Average Directional Movement Index Rating
    # 函数名:ADXR
    # 名称:平均趋向指数的趋向指数
    # 简介:使用ADXR指标,指标判断ADX趋势。 NOTE: The ADXR function has an unstable period.
    # real = ADXR(high, low, close, timeperiod=14)
    df["ADXR"] = talib.ADXR(df['high_price'], df['low_price'], df['close_price'], timeperiod=14)

    # APO - Absolute Price Oscillator
    # real = APO(close, fastperiod=12, slowperiod=26, matype=0)
    df["APO"] = talib.APO(df['close_price'], fastperiod=12, slowperiod=26, matype=0)
    # AROON - Aroon
    # 函数名:AROON
    # 名称:阿隆指标
    # 简介:该指标是通过计算自价格达到近期最高值和最低值以来所经过的期间数,阿隆指标帮助你预测价格趋势到趋势区域(或者反过来,从趋势区域到趋势)的变化。
    # 计算公式:
    # Aroon(上升)=[(计算期天数-最高价后的天数)/计算期天数]*100
    # Aroon(下降)=[(计算期天数-最低价后的天数)/计算期天数]*100
    # 指数应用
    # 1、极值0和100
    # 当UP线达到100时,市场处于强势;如果维持在70100之间,表示一个上升趋势。同样,如果Down线达到0,表示处于弱势,如果维持在030之间,表示处于下跌趋势。如果两条线同处于极值水平,则表明一个更强的趋势。
    # 2、平行运动
    # 如果两条线平行运动时,表明市场趋势被打破。可以预期该状况将持续下去,只到由极值水平或交叉穿行西安市出方向性运动为止。
    # 3、交叉穿行
    # 当下行线上穿上行线时,表明潜在弱势,预期价格开始趋于下跌。反之,表明潜在强势,预期价格趋于走高。
    # aroondown, aroonup = AROON(high, low, timeperiod=14)
    df["AROON_aroondown"], df["AROON_aroonup"] = talib.AROON(df['high_price'], df['low_price'], timeperiod=14)

    # AROONOSC - Aroon Oscillator
    # 函数名:AROONOSC
    # 名称:阿隆振荡
    # 简介:
    # real = AROONOSC(high, low, timeperiod=14)
    df["AROONOSC"] = talib.AROONOSC(df['high_price'], df['low_price'], timeperiod=14)
    # BOP - Balance Of Power 均势
    # 函数名:BOP
    # 名称:均势指标
    # 简介
    # real = BOP(open, high, low, close)
    df["BOP"] = talib.BOP(df['open_price'], df['high_price'], df['low_price'], df['close_price'])

    # CCI - Commodity Channel Index
    # 函数名:CCI
    # 名称:顺势指标
    # 简介:CCI指标专门测量股价是否已超出常态分布范围
    # 指标应用
    # 1.当CCI指标曲线在+100线~-100线的常态区间里运行时,CCI指标参考意义不大,可以用KDJ等其它技术指标进行研判。
    # 2.当CCI指标曲线从上向下突破+100线而重新进入常态区间时,表明市场价格的上涨阶段可能结束,将进入一个比较长时间的震荡整理阶段,应及时平多做空。
    # 3.当CCI指标曲线从上向下突破-100线而进入另一个非常态区间(超卖区)时,表明市场价格的弱势状态已经形成,将进入一个比较长的寻底过程,可以持有空单等待更高利润。如果CCI指标曲线在超卖区运行了相当长的一段时间后开始掉头向上,表明价格的短期底部初步探明,可以少量建仓。CCI指标曲线在超卖区运行的时间越长,确认短期的底部的准确度越高。
    # 4.CCI指标曲线从下向上突破-100线而重新进入常态区间时,表明市场价格的探底阶段可能结束,有可能进入一个盘整阶段,可以逢低少量做多。
    # 5.CCI指标曲线从下向上突破+100线而进入非常态区间(超买区)时,表明市场价格已经脱离常态而进入强势状态,如果伴随较大的市场交投,应及时介入成功率将很大。
    # 6.CCI指标曲线从下向上突破+100线而进入非常态区间(超买区)后,只要CCI指标曲线一直朝上运行,表明价格依然保持强势可以继续持有待涨。但是,如果在远离+100线的地方开始掉头向下时,则表明市场价格的强势状态将可能难以维持,涨势可能转弱,应考虑卖出。如果前期的短期涨幅过高同时价格回落时交投活跃,则应该果断逢高卖出或做空。
    # CCI主要是在超买和超卖区域发生作用,对急涨急跌的行情检测性相对准确。非常适用于股票、外汇、贵金属等市场的短期操作。[1]
    # real = CCI(high, low, close, timeperiod=14)
    df["CCI"] = talib.CCI(df['high_price'], df['low_price'], df['close_price'], timeperiod=14)
    # CMO - Chande Momentum Oscillator 钱德动量摆动指标
    # 函数名:CMO
    # 名称:钱德动量摆动指标
    # 简介:与其他动量指标摆动指标如相对强弱指标(RSI)和随机指标(KDJ)不同,钱德动量指标在计算公式的分子中采用上涨日和下跌日的数据。 计算公式:CMO=(Su-Sd)*100/(Su+Sd)
    # 其中:Su是今日收盘价与昨日收盘价(上涨日)差值加总。若当日下跌,则增加值为0;Sd是今日收盘价与做日收盘价(下跌日)差值的绝对值加总。若当日上涨,则增加值为0;
    # 指标应用
    # 本指标类似RSI指标。
    # 当本指标下穿-50水平时是买入信号,上穿+50水平是卖出信号。
    # 钱德动量摆动指标的取值介于-100和100之间。
    # 本指标也能给出良好的背离信号。
    # 当股票价格创出新低而本指标未能创出新低时,出现牛市背离;
    # 当股票价格创出新高而本指标未能创出新高时,当出现熊市背离时。
    # 我们可以用移动均值对该指标进行平滑。
    # NOTE: The CMO function has an unstable period.
    # real = CMO(close, timeperiod=14)
    df["CMO"] = talib.CMO(df['close_price'], timeperiod=14)

    # DX - Directional Movement Index DMI指标又叫动向指标或趋向指标
    # 函数名:DX
    # 名称:动向指标或趋向指标
    # 简介:通过分析股票价格在涨跌过程中买卖双方力量均衡点的变化情况,即多空双方的力量的变化受价格波动的影响而发生由均衡到失衡的循环过程,从而提供对趋势判断依据的一种技术指标。
    # 分析和应用:百度百科 维基百科 同花顺学院
    # NOTE: The DX function has an unstable period.
    # real = DX(high, low, close, timeperiod=14)
    df["DX"] = talib.DX(df['high_price'], df['low_price'], df['close_price'], timeperiod=14)

    # MACD - Moving Average Convergence/Divergence
    # 函数名:MACD
    # 名称:平滑异同移动平均线
    # 简介:利用收盘价的短期(常用为12日)指数移动平均线与长期(常用为26日)指数移动平均线之间的聚合与分离状况,对买进、卖出时机作出研判的技术指标。 分析和应用:百度百科 维基百科 同花顺学院
    # macd, macdsignal, macdhist = MACD(close, fastperiod=12, slowperiod=26, signalperiod=9)
    df["MACD_macd"], df["MACD_macdsignal"], df["MACD_macdhist"] = talib.MACD(df['close_price'], fastperiod=12,
                                                                             slowperiod=26, signalperiod=9)

    # MACDEXT - MACD with controllable MA type
    # 函数名:MACDEXT (这个是干啥的(o)?)
    # 名称:
    # macd, macdsignal, macdhist = MACDEXT(close, fastperiod=12, fastmatype=0, slowperiod=26, slowmatype=0, signalperiod=9, signalmatype=0)
    df["MACDEXT_macd"], df["MACDEXT_macdsignal"], df["MACDEXT_macdhist"] = talib.MACDEXT(df['close_price'],
                                                                                         fastperiod=12,
                                                                                         fastmatype=0,
                                                                                         slowperiod=26,
                                                                                         slowmatype=0,
                                                                                         signalperiod=9,
                                                                                         signalmatype=0)
    # MACDFIX - Moving Average Convergence/Divergence Fix 12/26
    # macd, macdsignal, macdhist = MACDFIX(close, signalperiod=9)
    df["MACDFIX_macd"], df["MACDFIX_macdsignal"], df["MACDFIX_macdhist"] = talib.MACDFIX(df['close_price'],
                                                                                         signalperiod=9)
    # MFI - Money Flow Index 资金流量指标
    # 函数名:MFI
    # 名称:资金流量指标
    # 简介:属于量价类指标,反映市场的运行趋势
    # 分析和应用:百度百科 同花顺学院
    # NOTE: The MFI function has an unstable period.
    # real = MFI(high, low, close, volume, timeperiod=14)
    df["MFI"] = talib.MFI(df['high_price'], df['low_price'], df['close_price'], df['volume'], timeperiod=14)

    # MINUS_DI - Minus Directional Indicator
    # 函数名:DMI 中的DI指标 负方向指标
    # 名称:下升动向值
    # 简介:通过分析股票价格在涨跌过程中买卖双方力量均衡点的变化情况,即多空双方的力量的变化受价格波动的影响而发生由均衡到失衡的循环过程,从而提供对趋势判断依据的一种技术指标。
    # 分析和应用:百度百科 维基百科 同花顺学院 NOTE: The MINUS_DI function has an unstable period.
    # real = MINUS_DI(high, low, close, timeperiod=14)
    df["MINUS_DI"] = talib.MINUS_DI(df['high_price'], df['low_price'], df['close_price'], timeperiod=14)

    # MINUS_DM - Minus Directional Movement
    # 函数名:MINUS_DM
    # 名称: 上升动向值 DMI中的DM代表正趋向变动值即上升动向值
    # 简介:通过分析股票价格在涨跌过程中买卖双方力量均衡点的变化情况,即多空双方的力量的变化受价格波动的影响而发生由均衡到失衡的循环过程,从而提供对趋势判断依据的一种技术指标。
    # 分析和应用:百度百科 维基百科 同花顺学院
    # NOTE: The MINUS_DM function has an unstable period.
    # real = MINUS_DM(high, low, timeperiod=14)
    df["MINUS_DM"] = talib.MINUS_DM(df['high_price'], df['low_price'], timeperiod=14)

    # MOM - Momentum 动量
    # 函数名:MOM
    # 名称: 上升动向值
    # 简介:投资学中意思为续航,指股票(或经济指数)持续增长的能力。研究发现,赢家组合在牛市中存在着正的动量效应,输家组合在熊市中存在着负的动量效应。
    # real = MOM(close, timeperiod=10)
    df["MOM"] = talib.MOM(df['close_price'], timeperiod=10)

    # PLUS_DI - Plus Directional Indicator
    # NOTE: The PLUS_DI function has an unstable period.
    # real = PLUS_DI(high, low, close, timeperiod=14)
    df["PLUS_DI"] = talib.PLUS_DI(df['high_price'], df['low_price'], df['close_price'], timeperiod=14)

    # PLUS_DM - Plus Directional Movement
    # NOTE: The PLUS_DM function has an unstable period.
    # real = PLUS_DM(high, low, timeperiod=14)
    df["PLUS_DM"] = talib.PLUS_DM(df['high_price'], df['low_price'], timeperiod=14)

    # PPO - Percentage Price Oscillator 价格震荡百分比指数
    # 函数名:PPO 名称: 价格震荡百分比指数
    # 简介:价格震荡百分比指标(PPO)是一个和MACD指标非常接近的指标。
    # PPO标准设定和MACD设定非常相似:12,26,9和PPO,和MACD一样说明了两条移动平均线的差距,但是它们有一个差别是PPO是用百分比说明。
    # real = PPO(close, fastperiod=12, slowperiod=26, matype=0)
    df["PPO"] = talib.PPO(df['close_price'], fastperiod=12, slowperiod=26, matype=0)

    # ROC - Rate of change : ((price/prevPrice)-1)*100 变动率指标
    # 函数名:ROC
    # 名称: 变动率指标
    # 简介:ROC是由当天的股价与一定的天数之前的某一天股价比较,其变动速度的大小,来反映股票市变动的快慢程度
    # 分析和应用:百度百科 同花顺学院
    # real = ROC(close, timeperiod=10)
    df["ROC"] = talib.ROC(df['close_price'], timeperiod=10)
    # ROCP - Rate of change Percentage: (price-prevPrice)/prevPrice
    # real = ROCP(close, timeperiod=10)
    df["ROCP"] = talib.ROCP(df['close_price'], timeperiod=10)
    # ROCR - Rate of change ratio: (price/prevPrice)
    # real = ROCR(close, timeperiod=10)
    df["ROCR"] = talib.ROCR(df['close_price'], timeperiod=10)
    # ROCR100 - Rate of change ratio 100 scale: (price/prevPrice)*100
    # real = ROCR100(close, timeperiod=10)
    df["ROCR100"] = talib.ROCR100(df['close_price'], timeperiod=10)

    # RSI - Relative Strength Index 相对强弱指数
    # 函数名:RSI
    # 名称:相对强弱指数
    # 简介:是通过比较一段时期内的平均收盘涨数和平均收盘跌数来分析市场买沽盘的意向和实力,从而作出未来市场的走势。
    # NOTE: The RSI function has an unstable period.
    # real = RSI(close, timeperiod=14)
    df["RSI"] = talib.RSI(df['close_price'], timeperiod=14)

    # STOCH - Stochastic 随机指标,俗称KD
    # 函数名:STOCH
    # 名称:随机指标,俗称KD
    # slowk, slowd = STOCH(high, low, close, fastk_period=5, slowk_period=3, slowk_matype=0, slowd_period=3, slowd_matype=0)
    df["STOCH_slowk"], df["STOCH_slowd"] = talib.STOCH(df['high_price'], df['low_price'], df['close_price'],
                                                       fastk_period=5, slowk_period=3, slowk_matype=0,
                                                       slowd_period=3, slowd_matype=0)

    # STOCHF - Stochastic Fast
    # fastk, fastd = STOCHF(high, low, close, fastk_period=5, fastd_period=3, fastd_matype=0)
    df["STOCHF_fastk"], df["STOCHF_fastd"] = talib.STOCHF(df['high_price'], df['low_price'], df['close_price'],
                                                          fastk_period=5, fastd_period=3, fastd_matype=0)

    # STOCHRSI - Stochastic Relative Strength Index
    # NOTE: The STOCHRSI function has an unstable period.
    # fastk, fastd = STOCHRSI(close, timeperiod=14, fastk_period=5, fastd_period=3, fastd_matype=0)
    # df["STOCHRSI_fastk"],df["STOCHRSI_fastd"] = talib.STOCHF(close, timeperiod=14, fastk_period=5, fastd_period=3, fastd_matype=0)

    # TRIX - 1-day Rate-Of-Change (ROC) of a Triple Smooth EMA
    # real = TRIX(close, timeperiod=30)
    df["TRIX"] = talib.TRIX(df['close_price'], timeperiod=30)

    # ULTOSC - Ultimate Oscillator 终极波动指标
    # 函数名:ULTOSC
    # 名称:终极波动指标
    # 简介:UOS是一种多方位功能的指标,除了趋势确认及超买超卖方面的作用之外,它的“突破”讯号不仅可以提供最适当的交易时机之外,更可以进一步加强指标的可靠度。
    # 分析和应用:百度百科 同花顺学院
    # real = ULTOSC(high, low, close, timeperiod1=7, timeperiod2=14, timeperiod3=28)
    df["ULTOSC"] = talib.ULTOSC(df['high_price'], df['low_price'], df['close_price'], timeperiod1=7, timeperiod2=14,
                                timeperiod3=28)
    # WILLR - Williams' %R 威廉指标
    # 函数名:WILLR
    # 名称:威廉指标
    # 简介:WMS表示的是市场处于超买还是超卖状态。股票投资分析方法主要有如下三种:基本分析、技术分析、演化分析。在实际应用中,它们既相互联系,又有重要区别。
    # 分析和应用:百度百科 维基百科 同花顺学院
    # real = WILLR(high, low, close, timeperiod=14)
    df["WILLR"] = talib.WILLR(df['high_price'], df['low_price'], df['close_price'], timeperiod=14)
    # Statistic Functions 统计学指标
    # BETA - Beta
    # 函数名:BETA
    # 名称:β系数也称为贝塔系数
    # 简介:一种风险指数,用来衡量个别股票或 股票基金相对于整个股市的价格波动情况 贝塔系数衡量股票收益相对于业绩评价基准收益的总体波动性,是一个相对指标。 β 越高,意味着股票相对于业绩评价基准的波动性越大。 β 大于 1 , 则股票的波动性大于业绩评价基准的波动性。反之亦然。 用途:
    # 1)计算资本成本,做出投资决策(只有回报率高于资本成本的项目才应投资);
    # 2)计算资本成本,制定业绩考核及激励标准;
    # 3)计算资本成本,进行资产估值(Beta是现金流贴现模型的基础);
    # 4)确定单个资产或组合的系统风险,用于资产组合的投资管理,特别是股指期货或其他金融衍生品的避险(或投机)
    # real = BETA(high, low, timeperiod=5)
    df["BETA"] = talib.BETA(df['high_price'], df['low_price'], timeperiod=5)

    # CORREL - Pearson's Correlation Coefficient (r)
    # 函数名:CORREL
    # 名称:皮尔逊相关系数
    # 简介:用于度量两个变量X和Y之间的相关(线性相关),其值介于-1与1之间
    # 皮尔逊相关系数是一种度量两个变量间相关程度的方法。它是一个介于 1 和 -1 之间的值, 其中,1 表示变量完全正相关, 0 表示无关,-1 表示完全负相关。
    # real = CORREL(high, low, timeperiod=30)
    df["CORREL"] = talib.CORREL(df['high_price'], df['low_price'], timeperiod=30)
    # LINEARREG - Linear Regression
    # 直线回归方程:当两个变量x与y之间达到显著地线性相关关系时,应用最小二乘法原理确定一条最优直线的直线方程y=a+bx,这条回归直线与个相关点的距离比任何其他直线与相关点的距离都小,是最佳的理想直线. 回归截距a:表示直线在y轴上的截距,代表直线的起点.
    # 回归系数b:表示直线的斜率,他的实际意义是说明x每变化一个单位时,影响y平均变动的数量. 即x每增加1单位,y变化b个单位.
    # 函数名:LINEARREG
    # 名称:线性回归
    # 简介:来确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法
    # 其表达形式为y = w'x+e,e为误差服从均值为0的正态分布。
    # real = LINEARREG(close, timeperiod=14)
    df["LINEARREG"] = talib.LINEARREG(df['close_price'], timeperiod=14)
    # LINEARREG_ANGLE - Linear Regression Angle
    # 函数名:LINEARREG_ANGLE
    # 名称:线性回归的角度
    # 简介:来确定价格的角度变化. 参考
    # real = LINEARREG_ANGLE(close, timeperiod=14)
    df["LINEARREG_ANGLE"] = talib.LINEARREG_ANGLE(df['close_price'], timeperiod=14)
    # LINEARREG_INTERCEPT - Linear Regression Intercept
    # 函数名:LINEARREG_INTERCEPT
    # 名称:线性回归截距
    # real = LINEARREG_INTERCEPT(close, timeperiod=14)
    df["LINEARREG_INTERCEPT"] = talib.LINEARREG_INTERCEPT(df['close_price'], timeperiod=14)
    # LINEARREG_SLOPE - Linear Regression Slope
    # 函数名:LINEARREG_SLOPE
    # 名称:线性回归斜率指标
    # real = LINEARREG_SLOPE(close, timeperiod=14)
    df["LINEARREG_SLOPE"] = talib.LINEARREG_SLOPE(df['close_price'], timeperiod=14)
    # STDDEV - Standard Deviation
    # 函数名:STDDEV
    # 名称:标准偏差
    # 简介:种量度数据分布的分散程度之标准,用以衡量数据值偏离算术平均值的程度。标准偏差越小,这些值偏离平均值就越少,反之亦然。标准偏差的大小可通过标准偏差与平均值的倍率关系来衡量。
    # real = STDDEV(close, timeperiod=5, nbdev=1)
    df["STDDEV"] = talib.STDDEV(df['close_price'], timeperiod=5, nbdev=1)
    # TSF - Time Series Forecast
    # 函数名:TSF
    # 名称:时间序列预测
    # 简介:一种历史资料延伸预测,也称历史引伸预测法。是以时间数列所能反映的社会经济现象的发展过程和规律性,进行引伸外推,预测其发展趋势的方法
    # real = TSF(close, timeperiod=14)
    df["TSF"] = talib.TSF(df['close_price'], timeperiod=14)

    # VAR - VAR
    # 函数名: VAR 名称:方差
    # 简介:方差用来计算每一个变量(观察值)与总体均数之间的差异。为避免出现离均差总和为零,离均差平方和受样本含量的影响,统计学采用平均离均差平方和来描述变量的变异程度
    # real = VAR(close, timeperiod=5, nbdev=1)
    df["VAR"] = talib.VAR(df['close_price'], timeperiod=5, nbdev=1)

    df['change'] = df['close_price'] - df['close_price'].shift(1)

    df.index = df['datetime']
    del df['datetime']
    del df['max_price']
    del df['min_price']
    df.sort_index()

    df.dropna(inplace=True)
    return df

def train_df(self,df):
    X = df[['close_price', 'high_price', 'low_price', 'open_price',
            'volume', 'MA10', 'MA20', 'MA30', 'MA60',  # 'SMA120', 'SMA256',
            'BBANDS_upper', 'BBANDS_middle', 'BBANDS_lower', 'DEMA', 'MA', 'EMA12',
            'EMA26', 'KAMA', 'SMA', 'MIDPOINT', 'SAR', 'T3', 'TEMA', 'MIDPRICE',
            'TRIMA', 'SAREXT', 'WMA', 'ATR', 'NATR', 'TRANGE', 'AD', 'ADOSC', 'OBV',
            'HT_DCPERIOD', 'HT_DCPHASE', 'HT_PHASOR_inphase',
            'HT_PHASOR_quadrature', 'HT_SINE_sine', 'HT_SINE_leadsine',
            'HT_TRENDMODE', '$GPRICE', 'MEDPRICE', 'TYPPRICE', 'WCLPRICE', 'ADX',
            'ADXR', 'APO', 'AROON_aroondown', 'AROON_aroonup', 'AROONOSC', 'BOP',
            'CCI', 'CMO', 'DX', 'MACD_macd', 'MACD_macdsignal', 'MACD_macdhist',
            'MACDEXT_macd', 'MACDEXT_macdsignal', 'MACDEXT_macdhist',
            'MACDFIX_macd', 'MACDFIX_macdsignal', 'MACDFIX_macdhist', 'MFI',
            'MINUS_DI', 'MINUS_DM', 'MOM', 'PLUS_DI', 'PLUS_DM', 'PPO', 'ROC',
            'ROCP', 'ROCR', 'ROCR100', 'RSI', 'STOCH_slowk', 'STOCH_slowd',
            'STOCHF_fastk', 'STOCHF_fastd', 'TRIX', 'ULTOSC', 'WILLR', 'BETA',
            'CORREL', 'LINEARREG', 'LINEARREG_ANGLE', 'LINEARREG_INTERCEPT',
            'LINEARREG_SLOPE', 'STDDEV', 'TSF', 'VAR']]
    # y = np.where(df["change"]>0,1,-1)
    y = df["mm"]

    X_length = X.shape[0]
    split = int(X_length * self.percent)

    X_train, X_test = X[:split], X[split:]
    y_train, y_test = y[:split], y[split:]
    model = RandomForestClassifier(max_depth=10, n_estimators=10,
                                   min_samples_leaf=10, random_state=3)
    model.fit(X_test, y_test)
    y_pred = model.predict(X_test)
    accuracy = accuracy_score(y_test, y_pred)
    print(self.load_num, "准确率: %.2f%%" % (accuracy * 100.0))
    ### 特征重要性
    # importances = model.feature_importances_
    # indices = np.argsort(importances)[::-1]
    # for f in range(X_train.shape[1]):
    #     print("%2d) %-*s %f" % (f + 1, 30, df.columns[1:][indices[f]], importances[indices[f]]))
    #     pass
    joblib.dump(model, "max_min.model")
    df.to_csv("all.csv")

    #self.load_model_check(X_test)

def load_model_check(self,X_test):
    # m2 = joblib.load("max_min.model")
    # # print(m1.feature_importances_)
    # # print(classification_report(y,m1.predict(X_test),))
    # y_pred = m2.predict(X_test)
    # from sklearn.metrics import accuracy_score  # 准确率
    # accuracy = accuracy_score(y_test, y_pred)
    # print("准确率: %.2f%%" % (accuracy * 100.0))
    #
    # print(type(X_test))

    m2 = joblib.load("max_min.model")
    # print(m1.feature_importances_)
    # print(classification_report(y,m1.predict(X_test),))
    #X_test = X_test[-1:]
    print(X_test)
    y_pred = m2.predict(X_test)
    print(y_pred)
    # print(X_test.index[0])
    if y_pred == 1:
        print("根据", X_test.index[0], "预测,上涨")
        return 1
    elif y_pred == -1:
        print("根据", X_test.index[0], "预测,下跌")
        return -1
    else:
        return 0


if name == 'main':
ml = Machinelearn(4, 0.9, "1h", "BTC-USD-SWAP")