VeighNa量化社区
你的开源社区量化交易平台
Member
avatar
加入于:
帖子: 4
声望: 0

from vnpy_ctastrategy import (
CtaTemplate,
StopOrder,
TickData,
BarData,
TradeData,
OrderData,
BarGenerator,
ArrayManager,
)

from .my_strategies_tool import NewBarGennerator
from vnpy.trader.constant import Interval

class DemoStrategy(CtaTemplate):
"""演示用的简单双均线"""

# 策略作者
author = "Smart Trader"

# 定义参数
fast_window = 10
slow_window = 20
fast_window1 = 10
slow_window1 = 20
k=5

# 定义变量
fast_ma0 = 0.0
fast_ma1 = 0.0
slow_ma0 = 0.0
slow_ma1 = 0.0

fast_ma01 = 0.0
fast_ma11 = 0.0
slow_ma01 = 0.0
slow_ma11 = 0.0

cross_over2=True
cross_below2=True


# 添加参数和变量名到对应的列表
parameters = ["fast_window", "slow_window","k","fast_window", "slow_window"]
variables = ["fast_ma0", "fast_ma1", "slow_ma0", "slow_ma1","fast_ma01", "fast_ma11", "slow_ma01", "slow_ma11","cross_over2","cross_below2"]

def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
    """"""
    super().__init__(cta_engine, strategy_name, vt_symbol, setting)

    # K线合成器:从Tick合成分钟K线用xzsde
    self.bg = BarGenerator(self.on_bar)
    self.bg15=NewBarGennerator(self.on_bar,  window=self.k, on_window_bar=self.on_5min_bar, interval=Interval.MINUTE)

    # 时间序列容器:计算技术指标用
    self.am = ArrayManager()
    self.am2=ArrayManager()

def on_init(self):
    """
    当策略被初始化时调用该函数。
    """
    # 输出个日志信息,下同
    self.write_log("策略初始化")

    # 加载10天的历史数据用于初始化回放
    self.load_bar(10)

def on_start(self):
    """
    当策略被启动时调用该函数。
    """
    self.write_log("策略启动")

    # 通知图形界面更新(策略最新状态)
    # 不调用该函数则界面不会变化
    self.put_event()

def on_stop(self):
    """
    当策略被停止时调用该函数。
    """
    self.write_log("策略停止")

    self.put_event()

def on_tick(self, tick: TickData):
    """
    通过该函数收到Tick推送。
    """
    self.bg.update_tick(tick)
    self.bg15.update_tick(tick)

def on_bar(self, bar: BarData):
    """
    通过该函数收到新的1分钟K线推送。
    """
    self.bg.update_bar(bar)
    self.bg15.update_bar(bar)
    am = self.am
    am.update_bar(bar)
    if not am.inited:
        return

    fast_ma1 = am.sma(self.fast_window1, array=True)
    self.fast_ma01 = fast_ma1[-1]     # T时刻数值
    self.fast_ma11 = fast_ma1[-2]     # T-1时刻数值

    # 计算慢速均线
    slow_ma1 = am.sma(self.slow_window1, array=True)
    self.slow_ma01 = slow_ma1[-1]
    self.slow_ma11 = slow_ma1[-2]

    # 判断是否金叉
    self.cross_over2 = (self.fast_ma01 > self.slow_ma01 and
                  self.fast_ma11 < self.slow_ma11)

    # 判断是否死叉
    self.cross_below2 = (self.fast_ma01 < self.slow_ma01 and
                   self.fast_ma11 > self.slow_ma11)


def on_5min_bar(self, bar: BarData):

    am2=self.am2

    # 更新K线到时间序列容器中

    am2.update_bar(bar)

    # 若缓存的K线数量尚不够计算技术指标,则直接返回

    if not am2.inited:
        return

    # 计算快速均线
    fast_ma = am2.sma(self.fast_window, array=True)
    self.fast_ma0 = fast_ma[-1]     # T时刻数值
    self.fast_ma1 = fast_ma[-2]     # T-1时刻数值

    # 计算慢速均线
    slow_ma = am2.sma(self.slow_window, array=True)
    self.slow_ma0 = slow_ma[-1]
    self.slow_ma1 = slow_ma[-2]

    # 判断是否金叉
    cross_over = (self.fast_ma0 > self.slow_ma0 and
                  self.fast_ma1 < self.slow_ma1)

    # 判断是否死叉
    cross_below = (self.fast_ma0 < self.slow_ma0 and
                   self.fast_ma1 > self.slow_ma1)

    # 如果发生了金叉
    if cross_over and self.cross_over2:
        # 为了保证成交,在K线收盘价上加5发出限价单
        price = bar.close_price + 5

        # 当前无仓位,则直接开多
        if self.pos == 0:
            self.buy(price, 1)
        # 当前持有空头仓位,则先平空,再开多
        elif self.pos < 0:
            self.cover(price, 1)
            self.buy(price, 1)

    # 如果发生了死叉
    elif cross_below and self.cross_below2:
        price = bar.close_price - 5

        # 当前无仓位,则直接开空
        if self.pos == 0:
            self.short(price, 1)
        # 当前持有空头仓位,则先平多,再开空
        elif self.pos > 0:
            self.sell(price, 1)
            self.short(price, 1)

    self.put_event()

def on_order(self, order: OrderData):
    """
    通过该函数收到委托状态更新推送。
    """
    pass

def on_trade(self, trade: TradeData):
    """
    通过该函数收到成交推送。
    """
    # 成交后策略逻辑仓位发生变化,需要通知界面更新。
    self.put_event()

def on_stop_order(self, stop_order: StopOrder):
    """
    通过该函数收到本地停止单推送。
    """
    pass





16:53:02 策略文件加载完成
16:53:18 ----------------------------------------
16:53:18 开始加载历史数据
16:53:18 加载进度:# [0%]
16:53:18 加载进度:# [10%]
16:53:19 加载进度:## [20%]
16:53:20 加载进度:### [30%]
16:53:21 加载进度:#### [39%]
16:53:21 加载进度:##### [49%]
16:53:22 加载进度:###### [59%]
16:53:23 加载进度:####### [69%]
16:53:23 加载进度:######## [79%]
16:53:23 加载进度:######### [89%]
16:53:23 加载进度:########## [99%]
16:53:23 历史数据加载完成,数据量:54945
16:53:23 触发异常,回测终止
16:53:23 Traceback (most recent call last):
File "C:\veighna_studio\lib\site-packages\vnpy_ctastrategy\backtesting.py", line 228, in run_backtesting
self.callback(data)
File "C:\Users\1\strategies\demo_strategy.py", line 98, in on_bar
self.bg.update_bar(bar)
File "C:\veighna_studio\lib\site-packages\vnpy\trader\utility.py", line 266, in update_bar
self.update_bar_minute_window(bar)
File "C:\veighna_studio\lib\site-packages\vnpy\trader\utility.py", line 302, in update_bar_minute_window
if not (bar.datetime.minute + 1) % self.window:
ZeroDivisionError: integer division or modulo by zero

16:53:23 开始计算逐日盯市盈亏
16:53:23 成交记录为空,无法计算
16:53:23 开始计算策略统计指标
16:53:23 策略统计指标计算完成

Member
avatar
加入于:
帖子: 420
声望: 175

答复:

1 问题代码修改:

def on_tick(self, tick: TickData):
    """
    通过该函数收到Tick推送。
    """
    self.bg.update_tick(tick)
    # self.bg15.update_tick(tick) # —— 先注释掉这一句

self.bg和self.bg15共用了同一个on_bar()函数,在tick到来的时候on_tick()只要调用周期较小self.bg的update_tick就可以生成1分钟bar了。无需两个都更新tick来得到两个相同的1分钟bar,然后又两次调用on_bar()函数,因为self.bg生成1分钟bar时会调用on_bar()函数,self.bg15也会生成一个相同的1分钟bar,它也会调用on_bar()函数,这不符合你的设计本意,对吧?
先这么改下看看。

Member
avatar
加入于:
帖子: 4
声望: 0

from vnpy_ctastrategy import (
CtaTemplate,
StopOrder,
TickData,
BarData,
TradeData,
OrderData,
BarGenerator,
ArrayManager,
)

from my_strategies_tool import NewBarGennerator

from vnpy.trader.constant import Interval

class DemoStrategy(CtaTemplate):
"""演示用的简单双均线"""

# 策略作者
author = "Smart Trader"

# 定义参数
fast_window = 10
slow_window = 20
fast_window1 = 10
slow_window1 = 20
k=5

# 定义变量
fast_ma0 = 0.0
fast_ma1 = 0.0
slow_ma0 = 0.0
slow_ma1 = 0.0

fast_ma01 = 0.0
fast_ma11 = 0.0
slow_ma01 = 0.0
slow_ma11 = 0.0

cross_over2=True
cross_below2=True


# 添加参数和变量名到对应的列表
parameters = ["fast_window", "slow_window","k","fast_window", "slow_window"]
variables = ["fast_ma0", "fast_ma1", "slow_ma0", "slow_ma1","fast_ma01", "fast_ma11", "slow_ma01", "slow_ma11","cross_over2","cross_below2"]

def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
    """"""
    super().__init__(cta_engine, strategy_name, vt_symbol, setting)

    # K线合成器:从Tick合成分钟K线用xzsde
    self.bg = BarGenerator(self.on_bar)
    self.bg15=BarGenerator(self.on_bar,  window=self.k, on_window_bar=self.on_5min_bar, interval=Interval.MINUTE)

    # 时间序列容器:计算技术指标用
    self.am = ArrayManager()
    self.am2=ArrayManager()

def on_init(self):
    """
    当策略被初始化时调用该函数。
    """
    # 输出个日志信息,下同
    self.write_log("策略初始化")

    # 加载10天的历史数据用于初始化回放
    self.load_bar(10)

def on_start(self):
    """
    当策略被启动时调用该函数。
    """
    self.write_log("策略启动")

    # 通知图形界面更新(策略最新状态)
    # 不调用该函数则界面不会变化
    self.put_event()

def on_stop(self):
    """
    当策略被停止时调用该函数。
    """
    self.write_log("策略停止")

    self.put_event()

def on_tick(self, tick: TickData):
    """
    通过该函数收到Tick推送。
    """
    self.bg.update_tick(tick)
    # self.bg15.update_tick(tick)

def on_bar(self, bar: BarData):
    """
    通过该函数收到新的1分钟K线推送。
    """
    self.bg.update_bar(bar)
    self.bg15.update_bar(bar)
    am = self.am
    am.update_bar(bar)
    if not am.inited:
        return

    fast_ma1 = am.sma(self.fast_window1, array=True)
    self.fast_ma01 = fast_ma1[-1]     # T时刻数值
    self.fast_ma11 = fast_ma1[-2]     # T-1时刻数值

    # 计算慢速均线
    slow_ma1 = am.sma(self.slow_window1, array=True)
    self.slow_ma01 = slow_ma1[-1]
    self.slow_ma11 = slow_ma1[-2]

    # 判断是否金叉
    self.cross_over2 = (self.fast_ma01 > self.slow_ma01 and
                  self.fast_ma11 < self.slow_ma11)

    # 判断是否死叉
    self.cross_below2 = (self.fast_ma01 < self.slow_ma01 and
                   self.fast_ma11 > self.slow_ma11)


def on_5min_bar(self, bar: BarData):

    am2=self.am2

    # 更新K线到时间序列容器中

    am2.update_bar(bar)

    # 若缓存的K线数量尚不够计算技术指标,则直接返回

    if not am2.inited:
        return

    # 计算快速均线
    fast_ma = am2.sma(self.fast_window, array=True)
    self.fast_ma0 = fast_ma[-1]     # T时刻数值
    self.fast_ma1 = fast_ma[-2]     # T-1时刻数值

    # 计算慢速均线
    slow_ma = am2.sma(self.slow_window, array=True)
    self.slow_ma0 = slow_ma[-1]
    self.slow_ma1 = slow_ma[-2]

    # 判断是否金叉
    cross_over = (self.fast_ma0 > self.slow_ma0 and
                  self.fast_ma1 < self.slow_ma1)

    # 判断是否死叉
    cross_below = (self.fast_ma0 < self.slow_ma0 and
                   self.fast_ma1 > self.slow_ma1)

    # 如果发生了金叉
    if cross_over and self.cross_over2:
        # 为了保证成交,在K线收盘价上加5发出限价单
        price = bar.close_price + 5

        # 当前无仓位,则直接开多
        if self.pos == 0:
            self.buy(price, 1)
        # 当前持有空头仓位,则先平空,再开多
        elif self.pos < 0:
            self.cover(price, 1)
            self.buy(price, 1)

    # 如果发生了死叉
    elif cross_below and self.cross_below2:
        price = bar.close_price - 5

        # 当前无仓位,则直接开空
        if self.pos == 0:
            self.short(price, 1)
        # 当前持有空头仓位,则先平多,再开空
        elif self.pos > 0:
            self.sell(price, 1)
            self.short(price, 1)

    self.put_event()

def on_order(self, order: OrderData):
    """
    通过该函数收到委托状态更新推送。
    """
    pass

def on_trade(self, trade: TradeData):
    """
    通过该函数收到成交推送。
    """
    # 成交后策略逻辑仓位发生变化,需要通知界面更新。
    self.put_event()

def on_stop_order(self, stop_order: StopOrder):
    """
    通过该函数收到本地停止单推送。
    """
    pass




18:01:23 策略文件加载完成
18:01:34 ----------------------------------------
18:01:34 开始加载历史数据
18:01:34 加载进度:# [0%]
18:01:34 加载进度:# [10%]
18:01:35 加载进度:## [20%]
18:01:36 加载进度:### [29%]
18:01:36 加载进度:#### [39%]
18:01:37 加载进度:##### [49%]
18:01:38 加载进度:###### [59%]
18:01:38 加载进度:####### [69%]
18:01:39 加载进度:######## [79%]
18:01:39 加载进度:######### [88%]
18:01:39 加载进度:########## [98%]
18:01:39 历史数据加载完成,数据量:54945
18:01:39 触发异常,回测终止
18:01:39 Traceback (most recent call last):
File "C:\veighna_studio\lib\site-packages\vnpy_ctastrategy\backtesting.py", line 228, in run_backtesting
self.callback(data)
File "C:\Users\1\strategies\demo_strategy.py", line 98, in on_bar
self.bg.update_bar(bar)
File "C:\veighna_studio\lib\site-packages\vnpy\trader\utility.py", line 266, in update_bar
self.update_bar_minute_window(bar)
File "C:\veighna_studio\lib\site-packages\vnpy\trader\utility.py", line 302, in update_bar_minute_window
if not (bar.datetime.minute + 1) % self.window:
ZeroDivisionError: integer division or modulo by zero

18:01:39 开始计算逐日盯市盈亏
18:01:39 成交记录为空,无法计算
18:01:39 开始计算策略统计指标
18:01:39 策略统计指标计算完成

按照您给的建议,我修改了,还是不行,不知道什么原因

Member
avatar
加入于:
帖子: 420
声望: 175

self.k 配置的时候是多少,不能够是0
错误已经提示了:
···
File "C:\veighna_studio\lib\site-packages\vnpy\trader\utility.py", line 302, in update_bar_minute_window
if not (bar.datetime.minute + 1) % self.window:
ZeroDivisionError: integer division or modulo by zero
···

Member
avatar
加入于:
帖子: 4
声望: 0

配置的是5

Member
avatar
加入于:
帖子: 420
声望: 175

文韬武略 wrote:

配置的是5

答复:

1、BarGenerator的update_bar_minute_window()有bug

文件D:\ProgramFiles\vnstudio\lib\site-packages\vnpy\trader\utility.py"中BarGenerator的update_bar_minute_window(bar)有bug,这样修改:

    def update_bar_minute_window(self, bar: BarData) -> None:
        """"""
        # If not inited, create window bar object
        if not self.window_bar:
            dt = bar.datetime.replace(second=0, microsecond=0)
            self.window_bar = BarData(
                symbol=bar.symbol,
                exchange=bar.exchange,
                datetime=dt,
                gateway_name=bar.gateway_name,
                open_price=bar.open_price,
                high_price=bar.high_price,
                low_price=bar.low_price
            )
        # Otherwise, update high/low price into window bar
        else:
            self.window_bar.high_price = max(
                self.window_bar.high_price,
                bar.high_price
            )
            self.window_bar.low_price = min(
                self.window_bar.low_price,
                bar.low_price
            )

        # Update close price/volume/turnover into window bar
        self.window_bar.close_price = bar.close_price
        self.window_bar.volume += bar.volume
        self.window_bar.turnover += bar.turnover
        self.window_bar.open_interest = bar.open_interest

        # Check if window bar completed
        if self.on_window_bar and self.window:  # hxxjava add
            if not (bar.datetime.minute + 1) % self.window:
                self.on_window_bar(self.window_bar)
                self.window_bar = None

2、这样修改策略来验证一下是否正确

from vnpy_ctastrategy import (
    CtaTemplate,
    StopOrder,
    TickData,
    BarData,
    TradeData,
    OrderData,
    BarGenerator,
    ArrayManager,
)

# from my_strategies_tool import NewBarGennerator
from vnpy.trader.constant import Interval

class DemoStrategy(CtaTemplate):
    """演示用的简单双均线"""

    # 策略作者
    author = "Smart Trader"

    # 定义参数
    fast_window = 10
    slow_window = 20
    fast_window1 = 10
    slow_window1 = 20
    k=5

    # 定义变量
    fast_ma0 = 0.0
    fast_ma1 = 0.0
    slow_ma0 = 0.0
    slow_ma1 = 0.0

    fast_ma01 = 0.0
    fast_ma11 = 0.0
    slow_ma01 = 0.0
    slow_ma11 = 0.0

    cross_over2=True
    cross_below2=True


    # 添加参数和变量名到对应的列表
    parameters = ["fast_window", "slow_window","k","fast_window", "slow_window"]
    variables = ["fast_ma0", "fast_ma1", "slow_ma0", "slow_ma1","fast_ma01", "fast_ma11", "slow_ma01", "slow_ma11","cross_over2","cross_below2"]

    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """"""
        super().__init__(cta_engine, strategy_name, vt_symbol, setting)

        # K线合成器:从Tick合成分钟K线用xzsde
        self.bg = BarGenerator(self.on_bar)
        self.bg15=BarGenerator(self.on_bar,  window=self.k, on_window_bar=self.on_5min_bar, interval=Interval.MINUTE)

        # 时间序列容器:计算技术指标用
        self.am = ArrayManager()
        self.am2=ArrayManager()

        self.bars_num = 0   # hxxjava add
        self.bars15_num = 0  # hxxjava add

    def on_init(self):
        """
        当策略被初始化时调用该函数。
        """
        # 输出个日志信息,下同
        self.write_log("策略初始化")

        # 加载10天的历史数据用于初始化回放
        self.load_bar(10)

    def on_start(self):
        """
        当策略被启动时调用该函数。
        """
        self.write_log("策略启动")

        # 通知图形界面更新(策略最新状态)
        # 不调用该函数则界面不会变化
        self.put_event()

    def on_stop(self):
        """
        当策略被停止时调用该函数。
        """
        self.write_log("策略停止")

        self.put_event()

    def on_tick(self, tick: TickData):
        """
        通过该函数收到Tick推送。
        """
        self.bg.update_tick(tick)
        # self.bg15.update_tick(tick)

    def on_bar(self, bar: BarData):
        """
        通过该函数收到新的1分钟K线推送。
        """
        self.bars_num += 1  # hxxjava add

        self.bg.update_bar(bar)
        self.bg15.update_bar(bar)

        am = self.am
        am.update_bar(bar)
        if not am.inited:
            return

        fast_ma1 = am.sma(self.fast_window1, array=True)
        self.fast_ma01 = fast_ma1[-1]     # T时刻数值
        self.fast_ma11 = fast_ma1[-2]     # T-1时刻数值

        # 计算慢速均线
        slow_ma1 = am.sma(self.slow_window1, array=True)
        self.slow_ma01 = slow_ma1[-1]
        self.slow_ma11 = slow_ma1[-2]

        # 判断是否金叉
        self.cross_over2 = (self.fast_ma01 > self.slow_ma01 and
                    self.fast_ma11 < self.slow_ma11)

        # 判断是否死叉
        self.cross_below2 = (self.fast_ma01 < self.slow_ma01 and
                    self.fast_ma11 > self.slow_ma11)


    def on_5min_bar(self, bar: BarData):

        self.bars15_num += 1   # hxxjava add
        print(f"1分钟bar到数量={self.bars_num} k分钟bar到数量={self.bars15_num}")   # hxxjava add

        am2=self.am2

        # 更新K线到时间序列容器中

        am2.update_bar(bar)

        # 若缓存的K线数量尚不够计算技术指标,则直接返回

        if not am2.inited:
            return

        # 计算快速均线
        fast_ma = am2.sma(self.fast_window, array=True)
        self.fast_ma0 = fast_ma[-1]     # T时刻数值
        self.fast_ma1 = fast_ma[-2]     # T-1时刻数值

        # 计算慢速均线
        slow_ma = am2.sma(self.slow_window, array=True)
        self.slow_ma0 = slow_ma[-1]
        self.slow_ma1 = slow_ma[-2]

        # 判断是否金叉
        cross_over = (self.fast_ma0 > self.slow_ma0 and
                    self.fast_ma1 < self.slow_ma1)

        # 判断是否死叉
        cross_below = (self.fast_ma0 < self.slow_ma0 and
                    self.fast_ma1 > self.slow_ma1)

        # 如果发生了金叉
        if cross_over and self.cross_over2:
            # 为了保证成交,在K线收盘价上加5发出限价单
            price = bar.close_price + 5

            # 当前无仓位,则直接开多
            if self.pos == 0:
                self.buy(price, 1)
            # 当前持有空头仓位,则先平空,再开多
            elif self.pos < 0:
                self.cover(price, 1)
                self.buy(price, 1)

        # 如果发生了死叉
        elif cross_below and self.cross_below2:
            price = bar.close_price - 5

            # 当前无仓位,则直接开空
            if self.pos == 0:
                self.short(price, 1)
            # 当前持有空头仓位,则先平多,再开空
            elif self.pos > 0:
                self.sell(price, 1)
                self.short(price, 1)

        self.put_event()

    def on_order(self, order: OrderData):
        """
        通过该函数收到委托状态更新推送。
        """
        pass

    def on_trade(self, trade: TradeData):
        """
        通过该函数收到成交推送。
        """
        # 成交后策略逻辑仓位发生变化,需要通知界面更新。
        self.put_event()

    def on_stop_order(self, stop_order: StopOrder):
        """
        通过该函数收到本地停止单推送。
        """
        pass

3、这是测试结果

1分钟bar的数量=10 k分钟bar的数量=2
2022-08-27 08:56:53 1分钟bar的数量=15 k分钟bar的数量=3
1分钟bar的数量=20 k分钟bar的数量=4
1分钟bar的数量=25 k分钟bar的数量=5
1分钟bar的数量=30 k分钟bar的数量=6
1分钟bar的数量=35 k分钟bar的数量=7
1分钟bar的数量=40 k分钟bar的数量=8
1分钟bar的数量=45 k分钟bar的数量=9
1分钟bar的数量=50 k分钟bar的数量=10
2022-08-27 08:56:53 1分钟bar的数量=55 k分钟bar的数量=11
1分钟bar的数量=60 k分钟bar的数量=12
1分钟bar的数量=65 k分钟bar的数量=13
1分钟bar的数量=70 k分钟bar的数量=14
1分钟bar的数量=75 k分钟bar的数量=15
1分钟bar的数量=80 k分钟bar的数量=16
1分钟bar的数量=85 k分钟bar的数量=17
1分钟bar的数量=90 k分钟bar的数量=18
1分钟bar的数量=95 k分钟bar的数量=19
1分钟bar的数量=100 k分钟bar的数量=20
1分钟bar的数量=105 k分钟bar的数量=21
1分钟bar的数量=110 k分钟bar的数量=22
1分钟bar的数量=115 k分钟bar的数量=23
1分钟bar的数量=120 k分钟bar的数量=24
1分钟bar的数量=125 k分钟bar的数量=25
1分钟bar的数量=130 k分钟bar的数量=26
1分钟bar的数量=135 k分钟bar的数量=27
1分钟bar的数量=140 k分钟bar的数量=28
1分钟bar的数量=145 k分钟bar的数量=29
1分钟bar的数量=150 k分钟bar的数量=30
1分钟bar的数量=155 k分钟bar的数量=31
1分钟bar的数量=160 k分钟bar的数量=32
1分钟bar的数量=165 k分钟bar的数量=33
1分钟bar的数量=170 k分钟bar的数量=34
 。。。 。。。
Member
avatar
加入于:
帖子: 4
声望: 0

好的,十分感谢您!

© 2015-2022 上海韦纳软件科技有限公司
备案服务号:沪ICP备18006526号

沪公网安备 31011502017034号

【用户协议】
【隐私政策】
【免责条款】