from vnpy.app.cta_strategy.template import CtaTemplate
from typing import Any
from vnpy.trader.object import BarData, Interval, TickData, TradeData, OrderData, Direction, Offset
from vnpy.trader.utility import BarGenerator, ArrayManager
from datetime import datetime
from vnpy.app.cta_strategy.backtesting import BacktestingEngine, OptimizationSetting
from vnpy.app.cta_strategy.base import StopOrder
import talib

class BitquantFixedInvestmentStrategy(CtaTemplate):

    author = "okweex"
    fixed_invest_money = 5000
    trade_times = 0

    trade_hour = 18

    parameters = ["trade_hour"]
    variables = []

    def __init__(
            self,
            cta_engine: Any,
            strategy_name: str,
            vt_symbol: str,
            setting: dict):
        super(BitquantFixedInvestmentStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting)

        self.bg = BarGenerator(self.on_bar, window=1, on_window_bar=self.on_hour_bar, interval=Interval.HOUR)
        self.am = ArrayManager(10)

    def on_init(self):
        print("on init")
        self.load_bar(3)

    def on_start(self):
        """
        Callback when strategy is started.
        """
        print("on_start strategy")

    def on_tick(self, tick: TickData):
        self.bg.update_tick(tick)

    def on_bar(self, bar: BarData):
        self.bg.update_bar(bar)

    def on_hour_bar(self, bar: BarData):

        self.cancel_all()  # 先撤单
        self.am.update_bar(bar)

        if not self.am.inited:
            return

        """
        datetime.datetime.isoweekday()返回的1-7代表周一--周日;
        date.weekday()返回的0-6代表周一--到周日
        而标准格式种%w 1-6表示周一--周六,0代表周日  54 * 2  108 
        """

        if bar.datetime.isoweekday() == 5 and bar.datetime.hour == 18:
            self.buy(bar.close_price, self.fixed_invest_money/bar.close_price)

        if bar.datetime.isoweekday() == 4 and bar.datetime.hour == 16:
            self.buy(bar.close_price, self.fixed_invest_money/bar.close_price)
        # if self.pos == 0:  # 没有仓位
        #     pass
        # elif self.pos > 0:  # 有多头仓位
        #     pass
        # elif self.pos < 0:   # 有空头仓位
        #     pass

    def on_trade(self, trade: TradeData):
        pass
        # if trade.direction == Direction.LONG and trade.offset == Offset.OPEN:
        #     self.trade_times += 1

    def on_order(self, order: OrderData):
        pass
        # print(f"on order {order}")

    def on_stop_order(self, stop_order: StopOrder):
        pass
        # print(f"on stop order {stop_order}")



if __name__ == '__main__':

    # 回测引擎初始化
    engine = BacktestingEngine()

    # 设置交易对产品的参数
    engine.set_parameters(
        vt_symbol="XBTUSD.BITMEX",  # 交易的标的
        interval=Interval.MINUTE,
        start=datetime(2018, 1, 1),  # 开始时间 4万 ---> 1_000_000
        rate=2/1000,  # 手续费
        slippage=0.0,  # 交易滑点
        size=1,  # 合约乘数
        pricetick=0.5,
        capital=1_000_000,  # 初始资金
        end=datetime(2019, 12, 1)  # 结束时间
    )

    # 添加策略
    engine.add_strategy(BitquantFixedInvestmentStrategy, {})

    # 加载
    engine.load_data()

    # # 运行回测
    engine.run_backtesting()

    # 统计结果
    engine.calculate_result()

    # 计算策略的统计指标 Sharp ratio, drawdown
    engine.calculate_statistics()

    # 绘制图表
    engine.show_chart()

    """
    "total_return": total_return,
    "annual_return": annual_return,
    "daily_return": daily_return,
    "return_std": return_std,
    "sharpe_ratio": sharpe_ratio,
    "return_drawdown_ratio": return_drawdown_ratio,
    """
    # setting = OptimizationSetting()
    # setting.set_target("sharpe_ratio")
    # setting.add_parameter("entry_window", 10, 300, 1)
    # setting.add_parameter("exit_window", 5, 50, 1)
    # setting.add_parameter("atr_window", 10, 50, 1)
    # engine.run_ga_optimization(setting)  # 遗传算法优化.

    # engine.run_optimization()  # 多线程优化.