import pandas

from op_forex.model.bar_model import BarModel

from op_forex.model.symbol_info import SymbolInfo
from op_forex.strategy.template_strategy import TemplateStrategy
from tqz_extern.tqz_constant import StrategyDirect
from op_forex.model.renko_block_model import RenkoBlockModel, RenkoColor
from op_forex.model.renko_wave_model import RenkoWaveModel


class SinglePeriodRenkoStrategy2(TemplateStrategy):

    author: str = 'Erwin'

    def __init__(self, fast_windows: int, slow_windows: int, renko_ticks: int):
        super().__init__()

        self.fast_windows: int = fast_windows
        self.slow_windows: int = slow_windows
        self.renko_ticks: int = renko_ticks
        self.atr_range_multi: int = 3

        self.hour_bars_df = pandas.DataFrame(columns=['time', 'high', 'open', 'low', 'close', 'volume'])

        self.his_renko_blocks: [RenkoBlockModel] = []
        self.his_renko_waves: [RenkoWaveModel] = []
        self.start_renko_price: float = None

        self.renko_size: float = None
        self.stop_loss_price: float = None

        self.lots: float = 0

    def on_init(self, symbol_info: SymbolInfo, strategy_direct: StrategyDirect):
        self.strategy_direct = strategy_direct

        self.symbol_info = symbol_info

        self.lots = self.symbol_info.volume_min

        self.renko_size = self.symbol_info.trade_tick_size * self.renko_ticks

    def on_bar(self, bar: BarModel = None):
        self.hour_bars_df.loc[len(self.hour_bars_df)] = [bar.time, bar.high, bar.open, bar.low, bar.close, bar.volume]
        if len(self.hour_bars_df) < self.slow_windows:
            return

        # - calculate part.
        fast_ma_value = self.hour_bars_df[-self.fast_windows:].close.mean()
        slow_ma_value = self.hour_bars_df[-self.slow_windows:].close.mean()

        atr_value = (self.hour_bars_df[-self.slow_windows:].high - self.hour_bars_df[-self.slow_windows:].low).mean() * self.atr_range_multi

        # - update renko_block, renko_wave.
        self.update_renko_block_renko_wave(cur_bar=bar)

        if len(self.his_renko_blocks) < 2:
            return
        if len(self.his_renko_waves) < 4:  # 如果是空间背驰, 则 self.his_renko_waves 至少有四个元素;
            return

        cur_renko, pre_renko = self.his_renko_blocks[-1], self.his_renko_blocks[-2]

        # - 策略逻辑
        if fast_ma_value > slow_ma_value:
            if self.pos < 0:
                self.buy(symbol=self.symbol_info.name, date_time=bar.time, price=bar.close, lots=abs(self.pos))
                self.stop_loss_price = None

            if 0 == self.pos:
                if RenkoColor.GREEN == pre_renko.renko_color and RenkoColor.RED == cur_renko.renko_color:  # 低点产生
                    if abs(self.his_renko_waves[-1].renko_wave_price - self.his_renko_waves[-2].renko_wave_price) < abs(self.his_renko_waves[-3].renko_wave_price - self.his_renko_waves[-4].renko_wave_price):  # 下降段 空间背驰.
                        self.buy(symbol=self.symbol_info.name, date_time=bar.time, price=bar.close, lots=self.lots)
                        self.stop_loss_price = bar.close - atr_value

            elif self.pos > 0:
                if bar.low <= self.stop_loss_price:  # 扫到止损
                    self.sell(symbol=self.symbol_info.name, date_time=bar.time, price=self.stop_loss_price, lots=self.pos)
                    self.stop_loss_price = None
                elif RenkoColor.RED == pre_renko.renko_color and RenkoColor.GREEN == cur_renko.renko_color:  # 高点产生
                    if abs(self.his_renko_waves[-1].renko_wave_price - self.his_renko_waves[-2].renko_wave_price) < abs(self.his_renko_waves[-3].renko_wave_price - self.his_renko_waves[-4].renko_wave_price):  # 上涨段 空间背驰.
                        self.sell(symbol=self.symbol_info.name, date_time=bar.time, price=bar.close, lots=self.pos)
                        self.stop_loss_price = None

        elif fast_ma_value < slow_ma_value:
            if self.pos > 0:
                self.sell(symbol=self.symbol_info.name, date_time=bar.time, price=bar.close, lots=self.pos)
                self.stop_loss_price = None

            if 0 == self.pos:
                if RenkoColor.RED == pre_renko.renko_color and RenkoColor.GREEN == cur_renko.renko_color:  # 高点
                    if abs(self.his_renko_waves[-1].renko_wave_price - self.his_renko_waves[-2].renko_wave_price) < abs(self.his_renko_waves[-3].renko_wave_price - self.his_renko_waves[-4].renko_wave_price):  # 上涨段 空间背驰.
                        self.sell(symbol=self.symbol_info.name, date_time=bar.time, price=bar.close, lots=self.lots)
                        self.stop_loss_price = bar.close + atr_value

            elif self.pos < 0:
                if bar.high >= self.stop_loss_price:
                    self.buy(symbol=self.symbol_info.name, date_time=bar.time, price=self.stop_loss_price, lots=abs(self.pos))
                    self.stop_loss_price = None
                elif RenkoColor.GREEN == pre_renko.renko_color and RenkoColor.RED == cur_renko.renko_color:  # 低点
                    if abs(self.his_renko_waves[-1].renko_wave_price - self.his_renko_waves[-2].renko_wave_price) < abs(self.his_renko_waves[-3].renko_wave_price - self.his_renko_waves[-4].renko_wave_price):  # 下降段 空间背驰.
                        self.buy(symbol=self.symbol_info.name, date_time=bar.time, price=bar.close, lots=abs(self.pos))
                        self.stop_loss_price = None


    def on_daily_bar(self, daily_bars_df: pandas.DataFrame = None):
        pass


    def on_stop(self):
        pass


    def update_renko_block_renko_wave(self, cur_bar: BarModel):
        if 0 == len(self.his_renko_blocks):
            if self.start_renko_price is None:
                self.start_renko_price = cur_bar.close
            else:
                if (self.start_renko_price + self.renko_size) <= cur_bar.close:  # new red renko
                    self.his_renko_blocks.append(
                        RenkoBlockModel(
                            renko_price=self.start_renko_price + ((cur_bar.close - self.start_renko_price) / self.renko_size) * self.renko_size,
                            renko_color=RenkoColor.RED,
                            renko_size=self.renko_size
                        )
                    )

                elif (self.start_renko_price - self.renko_size) >= cur_bar.close:  # new green renko
                    self.his_renko_blocks.append(
                        RenkoBlockModel(
                            renko_price=self.start_renko_price - ((self.start_renko_price - cur_bar.close) / self.renko_size) * self.renko_size,
                            renko_color=RenkoColor.GREEN,
                            renko_size=self.renko_size
                        )
                    )

        else:
            last_renko: RenkoBlockModel = self.his_renko_blocks[-1]
            if RenkoColor.RED == last_renko.renko_color:
                if (last_renko.renko_price + self.renko_size) <= cur_bar.close:  # new red renko
                    self.his_renko_blocks.append(
                        RenkoBlockModel(
                            renko_price=last_renko.renko_price + ((cur_bar.close - last_renko.renko_price) / self.renko_size) * self.renko_size,
                            renko_color=RenkoColor.RED,
                            renko_size=self.renko_size
                        )
                    )

                elif (last_renko.renko_price - 2 * self.renko_size) >= cur_bar.close:  # new green renko
                    self.his_renko_waves.append(
                        RenkoWaveModel(
                            renko_wave_price=last_renko.renko_price,
                            renko_color=RenkoColor.RED,
                            renko_size=self.renko_size
                        )
                    )

                    self.his_renko_blocks.append(
                        RenkoBlockModel(
                            renko_price=last_renko.renko_price - ((last_renko.renko_price - cur_bar.close) / self.renko_size) * self.renko_size,
                            renko_color=RenkoColor.GREEN,
                            renko_size=self.renko_size
                        )
                    )

            elif RenkoColor.GREEN == last_renko.renko_color:
                if (last_renko.renko_price + 2 * self.renko_size) <= cur_bar.close:  # new red renko
                    self.his_renko_waves.append(
                        RenkoWaveModel(
                            renko_wave_price=last_renko.renko_price,
                            renko_color=RenkoColor.GREEN,
                            renko_size=self.renko_size
                        )
                    )

                    self.his_renko_blocks.append(
                        RenkoBlockModel(
                            renko_price=last_renko.renko_price + ((cur_bar.close - last_renko.renko_price) / self.renko_size) * self.renko_size,
                            renko_color=RenkoColor.RED,
                            renko_size=self.renko_size
                        )
                    )

                elif (last_renko.renko_price - self.renko_size) >= cur_bar.close:  # new green renko
                    self.his_renko_blocks.append(
                        RenkoBlockModel(
                            renko_price=last_renko.renko_price - ((last_renko.renko_price - cur_bar.close) / self.renko_size) * self.renko_size,
                            renko_color=RenkoColor.GREEN,
                            renko_size=self.renko_size
                        )
                    )
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.
  • 143.
  • 144.
  • 145.
  • 146.
  • 147.
  • 148.
  • 149.
  • 150.
  • 151.
  • 152.
  • 153.
  • 154.
  • 155.
  • 156.
  • 157.
  • 158.
  • 159.
  • 160.
  • 161.
  • 162.
  • 163.
  • 164.
  • 165.
  • 166.
  • 167.
  • 168.
  • 169.
  • 170.
  • 171.
  • 172.
  • 173.
  • 174.
  • 175.
  • 176.
  • 177.
  • 178.
  • 179.
  • 180.
  • 181.
  • 182.
  • 183.
  • 184.
  • 185.
  • 186.
  • 187.
  • 188.
  • 189.
  • 190.
  • 191.
  • 192.