# encoding: UTF-8

'''
    实盘策略范例,接口用法见注释及范例代码
'''
import talib
from futuquant.examples.TinyQuant.TinyStrateBase import *
from futuquant import *
import datetime
import pandas as pd

class TinyStrateMACD(TinyStrateBase):
    """策略名称, setting.json中作为该策略配置的key"""
    name = 'tiny_strate_macd'

    """策略需要用到行情数据的股票池"""
    symbol_pools = ['HK.00700']



    pwd_unlock= '201791'


    def __init__(self):
       super(TinyStrateMACD, self).__init__()

       """请在setting.json中配置参数"""
       self.param1 = None
       self.param2 = None

    def on_init_strate(self):
        """策略加载完配置后的回调
        1. 可修改symbol_pools 或策略内部其它变量的初始化
        2. 此时还不能调用futu api的接口
        """

    def on_start(self):
        """策略启动完成后的回调
        1. 框架已经完成初始化, 可调用任意的futu api接口
        2. 修改symbol_pools无效, 不会有动态的行情数据回调
        """
        self.log("on_start param1=%s param2=%s" %(self.param1, self.param2))
        pass

    def on_quote_changed(self, tiny_quote):
        """报价、摆盘实时数据变化时,会触发该回调"""
        pass

    def on_bar_min1(self, tiny_bar):
        """每一分钟触发一次回调"""

        symbol = self.symbol_pools[0]

        now = datetime.datetime.now()
        work_time = now.replace(hour=15, minute=55, second=0)

        if now == work_time:
            quote_ctx = OpenQuoteContext(host='172.24.31.139', port=11111)
            data = tiny_bar
            price = data.open
            start_day = (now - datetime.timedelta(days=100)).strftime('%Y-%m-%d')
            end_day = now.strftime('%Y-%m-%d')
            history_result, history_kline_result = quote_ctx.get_history_kline(symbol, start=start_day, end=end_day)
            result, kline_result = quote_ctx.get_history_kline(symbol, start=start_day, end=end_day, ktype='K_5M')
            if history_result == 0 and result == 0 and history_kline_result.shape[0] >= 25 and kline_result.shape[0] > 0 :
                close_price = kline_result[-1:]
                close_price_array = history_kline_result['close']
                close_price_array.append(close_price)
                df = pd.DataFrame()
                df['EMA12'] = talib.EMA(np.array(close_price_array), timeperiod=6)
                df['EMA26'] = talib.EMA(np.array(close_price_array), timeperiod=12)
                df['MACD'], df['MACDsignal'], df['MACDhist'] = talib.MACD(np.array(close_price_array), fastperiod=6, slowperiod=12, signalperiod=9)
                signal = df['MACDsignal'][-1:].values[0]
                if signal > 0:
                    self.do_trade(symbol, price, "buy")
                elif signal <0:
                    self.do_trade(symbol, price, "sell")
            quote_ctx = OpenQuoteContext(host='172.24.31.139', port=11111)






    def on_bar_day(self, tiny_bar):
        """收盘时会触发一次日k回调"""
        pass

    def on_before_trading(self, date_time):
        """开盘时触发一次回调, 脚本挂机切换交易日时,港股会在09:30:00回调"""
        # 取前26个交易日的收盘价


        str_log = "on_before_trading - %s" % date_time.strftime('%Y-%m-%d %H:%M:%S')
        self.log(str_log)

    def on_after_trading(self, date_time):
        """收盘时触发一次回调, 脚本挂机时,港股会在16:00:00回调"""
        str_log = "on_after_trading - %s" % date_time.strftime('%Y-%m-%d %H:%M:%S')
        self.log(str_log)

    def ema(self, np_array, n, array=False):
        """移动均线"""
        if n < 2:
            result = np_array
        else:
            result = talib.EMA(np_array, n)
        if array:
            return result
        return result[-1]

    def do_trade(self, symbol, price, trd_side):
        # 获取账户信息
        trd_ctx = OpenHKTradeContext(host='172.24.31.139', port=11111)
        trd_ctx.unlock_trade(self.pwd_unlock)
        result, accinfo = trd_ctx.accinfo_query()
        if result != 0:
            return
        accinfo_cash = accinfo.cash.values[0]
        accinfo_market_val = accinfo.market_val.values[0]


        if trd_side == 'buy':
            qty = int(accinfo_cash / price)
            trd_ctx.place_order(price=price, qty=qty, code=symbol, trd_side=TrdSide.BUY)
        elif trd_side == 'sell':
            qty = int(accinfo_market_val / price)
            trd_ctx.place_order(price=price, qty=qty, code=symbol, trd_side=TrdSide.SELL)

        trd_ctx.close()