[调整CTA基础组件]
This commit is contained in:
parent
4ffbd50496
commit
000ccfef81
@ -1,18 +1,13 @@
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from vnpy.trader.app import BaseApp
|
from vnpy.trader.app import BaseApp
|
||||||
from vnpy.trader.constant import Direction,Offset,Status,Color
|
from .base import APP_NAME, StopOrder
|
||||||
from vnpy.trader.object import TickData, BarData, TradeData, OrderData
|
|
||||||
from vnpy.trader.utility import BarGenerator, ArrayManager
|
|
||||||
from .cta_position import CtaPosition
|
|
||||||
from .cta_line_bar import CtaLineBar, CtaMinuteBar, CtaHourBar, CtaDayBar, CtaWeekBar
|
|
||||||
from .base import APP_NAME, StopOrder, CtaComponent
|
|
||||||
from .cta_policy import CtaPolicy
|
|
||||||
from .cta_grid_trade import CtaGrid, CtaGridTrade
|
|
||||||
|
|
||||||
from .engine import CtaEngine
|
from .engine import CtaEngine
|
||||||
|
|
||||||
from .template import CtaTemplate, CtaSignal, TargetPosTemplate, CtaProTemplate, CtaProFutureTemplate
|
from .template import CtaTemplate, CtaSignal, TargetPosTemplate, CtaProTemplate, CtaProFutureTemplate
|
||||||
|
from .template_spread import CtaSpreadTemplate
|
||||||
|
|
||||||
|
|
||||||
class CtaStrategyProApp(BaseApp):
|
class CtaStrategyProApp(BaseApp):
|
||||||
""""""
|
""""""
|
||||||
|
@ -132,7 +132,7 @@ class BackTestingEngine(object):
|
|||||||
self.long_position_list = [] # 多单持仓
|
self.long_position_list = [] # 多单持仓
|
||||||
self.short_position_list = [] # 空单持仓
|
self.short_position_list = [] # 空单持仓
|
||||||
|
|
||||||
self.holdings = {} # 多空持仓
|
self.holdings = {} # 多空持仓
|
||||||
|
|
||||||
# 当前最新数据,用于模拟成交用
|
# 当前最新数据,用于模拟成交用
|
||||||
self.gateway_name = u'BackTest'
|
self.gateway_name = u'BackTest'
|
||||||
@ -370,7 +370,7 @@ class BackTestingEngine(object):
|
|||||||
holding = self.holdings.get(k, None)
|
holding = self.holdings.get(k, None)
|
||||||
if not holding:
|
if not holding:
|
||||||
symbol, exchange = extract_vt_symbol(vt_symbol)
|
symbol, exchange = extract_vt_symbol(vt_symbol)
|
||||||
if self.contract_type== 'future':
|
if self.contract_type == 'future':
|
||||||
product = Product.FUTURES
|
product = Product.FUTURES
|
||||||
elif self.contract_type == 'stock':
|
elif self.contract_type == 'stock':
|
||||||
product = Product.EQUITY
|
product = Product.EQUITY
|
||||||
@ -1901,7 +1901,7 @@ class BackTestingEngine(object):
|
|||||||
self.daily_max_drawdown_rate = drawdown_rate
|
self.daily_max_drawdown_rate = drawdown_rate
|
||||||
self.max_drawdown_rate_time = data['date']
|
self.max_drawdown_rate_time = data['date']
|
||||||
|
|
||||||
msg = u'{}: net={}, capital={} max={} margin={} commission={}, pos: {}'\
|
msg = u'{}: net={}, capital={} max={} margin={} commission={}, pos: {}' \
|
||||||
.format(data['date'],
|
.format(data['date'],
|
||||||
data['net'], c, m,
|
data['net'], c, m,
|
||||||
today_holding_profit,
|
today_holding_profit,
|
||||||
@ -1916,11 +1916,13 @@ class BackTestingEngine(object):
|
|||||||
# 今仓 =》 昨仓
|
# 今仓 =》 昨仓
|
||||||
for holding in self.holdings.values():
|
for holding in self.holdings.values():
|
||||||
if holding.long_td > 0:
|
if holding.long_td > 0:
|
||||||
self.write_log(f'{holding.vt_symbol} 多单今仓{holding.long_td},昨仓:{holding.long_yd}=> 昨仓:{holding.long_pos}')
|
self.write_log(
|
||||||
|
f'{holding.vt_symbol} 多单今仓{holding.long_td},昨仓:{holding.long_yd}=> 昨仓:{holding.long_pos}')
|
||||||
holding.long_td = 0
|
holding.long_td = 0
|
||||||
holding.long_yd = holding.long_pos
|
holding.long_yd = holding.long_pos
|
||||||
if holding.short_td > 0:
|
if holding.short_td > 0:
|
||||||
self.write_log(f'{holding.vt_symbol} 空单今仓{holding.short_td},昨仓:{holding.short_yd}=> 昨仓:{holding.short_pos}')
|
self.write_log(
|
||||||
|
f'{holding.vt_symbol} 空单今仓{holding.short_td},昨仓:{holding.short_yd}=> 昨仓:{holding.short_pos}')
|
||||||
holding.short_td = 0
|
holding.short_td = 0
|
||||||
holding.short_yd = holding.short_pos
|
holding.short_yd = holding.short_pos
|
||||||
|
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
"""
|
"""
|
||||||
Defines constants and objects used in CtaStrategyPro App.
|
Defines constants and objects used in CtaStrategyPro App.
|
||||||
"""
|
"""
|
||||||
import sys
|
|
||||||
from abc import ABC
|
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from logging import INFO, ERROR
|
|
||||||
from vnpy.trader.constant import Direction, Offset, Interval
|
from vnpy.trader.constant import Direction, Offset, Interval
|
||||||
|
|
||||||
APP_NAME = "CtaStrategyPro"
|
APP_NAME = "CtaStrategyPro"
|
||||||
@ -29,46 +27,6 @@ class BacktestingMode(Enum):
|
|||||||
TICK = 2
|
TICK = 2
|
||||||
|
|
||||||
|
|
||||||
class Area(Enum):
|
|
||||||
""" Kline area """
|
|
||||||
LONG_A = 'LONG_A'
|
|
||||||
LONG_B = 'LONG_B'
|
|
||||||
LONG_C = 'LONG_C'
|
|
||||||
LONG_D = 'LONG_D'
|
|
||||||
LONG_E = 'LONG_E'
|
|
||||||
SHORT_A = 'SHORT_A'
|
|
||||||
SHORT_B = 'SHORT_B'
|
|
||||||
SHORT_C = 'SHORT_C'
|
|
||||||
SHORT_D = 'SHORT_D'
|
|
||||||
SHORT_E = 'SHORT_E'
|
|
||||||
|
|
||||||
|
|
||||||
# 各类商品所在市场,underly_symbol: price_tick
|
|
||||||
# 上期所夜盘,9:00~10:15, 10:30~11:30, 13:30~15:00, 21:00 ~2:30
|
|
||||||
NIGHT_MARKET_SQ1 = {'AU': 0.05, 'AG': 1, 'SC': 0.1}
|
|
||||||
# 上期所夜盘,9:00~10:15, 10:30~11:30, 13:30~15:00, 21:00 ~1:00
|
|
||||||
NIGHT_MARKET_SQ2 = {'CU': 10, 'PB': 5, 'AL': 5, 'ZN': 5, 'WR': 1, 'NI': 10}
|
|
||||||
# 上期所夜盘,9:00~10:15, 10:30~11:30, 13:30~15:00, 21:00 ~23:00
|
|
||||||
NIGHT_MARKET_SQ3 = {'RU': 5, 'RB': 1, 'HC': 1, 'SP': 2, 'FU': 1, 'BU': 2, 'NR': 5, 'C': 1, 'CS': 1}
|
|
||||||
# 郑商所夜盘,9:00~10:15, 10:30~11:30, 13:30~15:00, 21:00 ~23:00
|
|
||||||
NIGHT_MARKET_ZZ = {'TA': 2, 'JR': 1, 'OI': 0, 'RO': 1, 'PM': 1, 'WH': 1, 'CF': 5, 'SR': 0, 'FG': 1,
|
|
||||||
'MA': 1, 'RS': 1, 'RM': 1, 'RI': 1, 'ZC': 0.2}
|
|
||||||
# 大商所夜盘,9:00~10:15, 10:30~11:30, 13:30~15:00, 21:00 ~23:00
|
|
||||||
NIGHT_MARKET_DL = {'V': 5, 'L': 5, 'BB': 0.05, 'I': 0.5, 'FB': 0.05, 'C': 1, 'PP': 1, 'A': 1, 'B': 1, 'M': 1, 'Y': 2,
|
|
||||||
'P': 2,
|
|
||||||
'JM': 0.5, 'J': 0.5, 'EG': 1}
|
|
||||||
# 中金日盘,9:15 ~11:30, 13:00~15:15
|
|
||||||
MARKET_ZJ = {'IC': 0.2, 'IF': 0.2, 'IH': 0.2, 'T': 0.005, 'TF': 0.005, 'TS': 0.005}
|
|
||||||
|
|
||||||
# 只有日盘得合约
|
|
||||||
MARKET_DAY_ONLY = {'IC': 0.2, 'IF': 0.2, 'IH': 0.2, 'T': 0.005, 'TF': 0.005, 'TS': 0.005,
|
|
||||||
'JD': 1, 'BB': 0.05, 'CS': 1, 'FB': 0.05, 'L': 5, 'V': 5,
|
|
||||||
'JR': 1, 'LR': 1, 'PM': 1, 'RI': 1, 'RS': 1, 'SM': 2, 'WH': 1, 'AP': 1, 'CJ': 1, 'UR': 1}
|
|
||||||
|
|
||||||
# 夜盘23:00收盘的合约
|
|
||||||
NIGHT_MARKET_23 = {**NIGHT_MARKET_DL, **NIGHT_MARKET_ZZ, **NIGHT_MARKET_SQ3}
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class StopOrder:
|
class StopOrder:
|
||||||
vt_symbol: str
|
vt_symbol: str
|
||||||
@ -93,28 +51,3 @@ INTERVAL_DELTA_MAP = {
|
|||||||
Interval.HOUR: timedelta(hours=1),
|
Interval.HOUR: timedelta(hours=1),
|
||||||
Interval.DAILY: timedelta(days=1),
|
Interval.DAILY: timedelta(days=1),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class CtaComponent(ABC):
|
|
||||||
""" CTA策略基础组件"""
|
|
||||||
|
|
||||||
def __init__(self, strategy=None, **kwargs):
|
|
||||||
"""
|
|
||||||
构造
|
|
||||||
:param strategy:
|
|
||||||
"""
|
|
||||||
self.strategy = strategy
|
|
||||||
|
|
||||||
def write_log(self, content: str):
|
|
||||||
"""记录日志"""
|
|
||||||
if self.strategy:
|
|
||||||
self.strategy.write_log(msg=content, level=INFO)
|
|
||||||
else:
|
|
||||||
print(content)
|
|
||||||
|
|
||||||
def write_error(self, content: str, level: int = ERROR):
|
|
||||||
"""记录错误日志"""
|
|
||||||
if self.strategy:
|
|
||||||
self.strategy.write_log(msg=content, level=level)
|
|
||||||
else:
|
|
||||||
print(content, file=sys.stderr)
|
|
||||||
|
@ -60,11 +60,10 @@ from .base import (
|
|||||||
StopOrder,
|
StopOrder,
|
||||||
StopOrderStatus,
|
StopOrderStatus,
|
||||||
STOPORDER_PREFIX,
|
STOPORDER_PREFIX,
|
||||||
MARKET_DAY_ONLY
|
|
||||||
|
|
||||||
)
|
)
|
||||||
from .template import CtaTemplate
|
from .template import CtaTemplate
|
||||||
from .cta_position import CtaPosition
|
from vnpy.component.base import MARKET_DAY_ONLY
|
||||||
|
from vnpy.component.cta_position import CtaPosition
|
||||||
|
|
||||||
STOP_STATUS_MAP = {
|
STOP_STATUS_MAP = {
|
||||||
Status.SUBMITTING: StopOrderStatus.WAITING,
|
Status.SUBMITTING: StopOrderStatus.WAITING,
|
||||||
|
@ -12,7 +12,7 @@ import os
|
|||||||
import gc
|
import gc
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
import traceback
|
import traceback
|
||||||
import random
|
|
||||||
import bz2
|
import bz2
|
||||||
import pickle
|
import pickle
|
||||||
|
|
||||||
@ -21,15 +21,12 @@ from time import sleep
|
|||||||
|
|
||||||
from vnpy.trader.object import (
|
from vnpy.trader.object import (
|
||||||
TickData,
|
TickData,
|
||||||
BarData,
|
|
||||||
RenkoBarData,
|
|
||||||
)
|
)
|
||||||
from vnpy.trader.constant import (
|
from vnpy.trader.constant import (
|
||||||
Exchange,
|
Exchange,
|
||||||
)
|
)
|
||||||
|
|
||||||
from vnpy.trader.utility import (
|
from vnpy.trader.utility import (
|
||||||
get_trading_date,
|
|
||||||
extract_vt_symbol,
|
extract_vt_symbol,
|
||||||
get_underlying_symbol,
|
get_underlying_symbol,
|
||||||
import_module_by_str
|
import_module_by_str
|
||||||
@ -46,6 +43,7 @@ VN_EXCHANGE_TICKFOLDER_MAP = {
|
|||||||
Exchange.INE.value: 'SQ'
|
Exchange.INE.value: 'SQ'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class SpreadTestingEngine(BackTestingEngine):
|
class SpreadTestingEngine(BackTestingEngine):
|
||||||
"""
|
"""
|
||||||
CTA套利组合回测引擎, 使用回测引擎作为父类
|
CTA套利组合回测引擎, 使用回测引擎作为父类
|
||||||
@ -231,7 +229,6 @@ class SpreadTestingEngine(BackTestingEngine):
|
|||||||
tick_date.strftime('%Y%m%d'),
|
tick_date.strftime('%Y%m%d'),
|
||||||
'{}{}_{}.csv'.format(underly_symbol.upper(), symbol[-2:], tick_date.strftime('%Y%m%d'))))
|
'{}{}_{}.csv'.format(underly_symbol.upper(), symbol[-2:], tick_date.strftime('%Y%m%d'))))
|
||||||
|
|
||||||
|
|
||||||
ticks = []
|
ticks = []
|
||||||
if not os.path.isfile(file_path):
|
if not os.path.isfile(file_path):
|
||||||
self.write_log(u'{0}文件不存在'.format(file_path))
|
self.write_log(u'{0}文件不存在'.format(file_path))
|
||||||
@ -307,8 +304,8 @@ class SpreadTestingEngine(BackTestingEngine):
|
|||||||
for vt_symbol in list(self.symbol_strategy_map.keys()):
|
for vt_symbol in list(self.symbol_strategy_map.keys()):
|
||||||
symbol, exchange = extract_vt_symbol(vt_symbol)
|
symbol, exchange = extract_vt_symbol(vt_symbol)
|
||||||
tick_list = self.load_csv_file(tick_folder=self.tick_path,
|
tick_list = self.load_csv_file(tick_folder=self.tick_path,
|
||||||
vt_symbol=vt_symbol,
|
vt_symbol=vt_symbol,
|
||||||
tick_date=test_day)
|
tick_date=test_day)
|
||||||
if not tick_list or len(tick_list) == 0:
|
if not tick_list or len(tick_list) == 0:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -16,8 +16,8 @@ from vnpy.trader.object import BarData, TickData, OrderData, TradeData
|
|||||||
from vnpy.trader.utility import virtual, append_data, extract_vt_symbol, get_underlying_symbol
|
from vnpy.trader.utility import virtual, append_data, extract_vt_symbol, get_underlying_symbol
|
||||||
|
|
||||||
from .base import StopOrder, EngineType
|
from .base import StopOrder, EngineType
|
||||||
from .cta_grid_trade import CtaGrid, CtaGridTrade, LOCK_GRID
|
from vnpy.component.cta_grid_trade import CtaGrid, CtaGridTrade, LOCK_GRID
|
||||||
from .cta_position import CtaPosition
|
from vnpy.component.cta_position import CtaPosition
|
||||||
|
|
||||||
|
|
||||||
class CtaTemplate(ABC):
|
class CtaTemplate(ABC):
|
||||||
|
@ -33,8 +33,8 @@ class CtaSpreadTemplate(CtaTemplate):
|
|||||||
|
|
||||||
backtesting = False
|
backtesting = False
|
||||||
cancel_seconds = 120
|
cancel_seconds = 120
|
||||||
allow_trading_open = True # 允许开仓
|
allow_trading_open = True # 允许开仓
|
||||||
force_trading_close = False # 强制平仓
|
force_trading_close = False # 强制平仓
|
||||||
|
|
||||||
# 逻辑过程日志
|
# 逻辑过程日志
|
||||||
dist_fieldnames = ['datetime', 'symbol', 'volume', 'price',
|
dist_fieldnames = ['datetime', 'symbol', 'volume', 'price',
|
||||||
@ -815,7 +815,7 @@ class CtaSpreadTemplate(CtaTemplate):
|
|||||||
# 开空委托单
|
# 开空委托单
|
||||||
if order_info['direction'] == Direction.SHORT:
|
if order_info['direction'] == Direction.SHORT:
|
||||||
short_price = self.cta_engine.get_price(order_vt_symbol) \
|
short_price = self.cta_engine.get_price(order_vt_symbol) \
|
||||||
- self.cta_engine.get_price_tick(order_vt_symbol)
|
- self.cta_engine.get_price_tick(order_vt_symbol) # noqa
|
||||||
|
|
||||||
self.write_log(u'重新提交{}开空委托,开空价{},v:{}'
|
self.write_log(u'重新提交{}开空委托,开空价{},v:{}'
|
||||||
.format(order_vt_symbol, short_price, order_volume))
|
.format(order_vt_symbol, short_price, order_volume))
|
||||||
@ -834,7 +834,7 @@ class CtaSpreadTemplate(CtaTemplate):
|
|||||||
else:
|
else:
|
||||||
|
|
||||||
buy_price = self.cta_engine.get_price(order_vt_symbol) \
|
buy_price = self.cta_engine.get_price(order_vt_symbol) \
|
||||||
+ self.cta_engine.get_price_tick(order_vt_symbol)
|
+ self.cta_engine.get_price_tick(order_vt_symbol) # noqa
|
||||||
self.write_log(u'重新提交{}开多委托,开多价{},v:{}'
|
self.write_log(u'重新提交{}开多委托,开多价{},v:{}'
|
||||||
.format(order_vt_symbol, buy_price, order_volume))
|
.format(order_vt_symbol, buy_price, order_volume))
|
||||||
vt_orderids = self.buy(price=buy_price,
|
vt_orderids = self.buy(price=buy_price,
|
||||||
@ -869,8 +869,9 @@ class CtaSpreadTemplate(CtaTemplate):
|
|||||||
# 属于平空委托单
|
# 属于平空委托单
|
||||||
else:
|
else:
|
||||||
cover_price = self.cta_engine.get_price(order_vt_symbol) \
|
cover_price = self.cta_engine.get_price(order_vt_symbol) \
|
||||||
+ self.cta_engine.get_price_tick(order_vt_symbol)
|
+ self.cta_engine.get_price_tick(order_vt_symbol) # noqa
|
||||||
self.write_log(u'重新提交{}平空委托,委托价{},v:{}'.format(order_vt_symbol, cover_price, order_volume))
|
self.write_log(u'重新提交{}平空委托,委托价{},v:{}'
|
||||||
|
.format(order_vt_symbol, cover_price, order_volume))
|
||||||
vt_orderids = self.cover(price=cover_price,
|
vt_orderids = self.cover(price=cover_price,
|
||||||
volume=order_volume,
|
volume=order_volume,
|
||||||
vt_symbol=order_vt_symbol,
|
vt_symbol=order_vt_symbol,
|
||||||
@ -975,11 +976,11 @@ class CtaSpreadTemplate(CtaTemplate):
|
|||||||
|
|
||||||
# 开空主动腿
|
# 开空主动腿
|
||||||
act_vt_orderids = self.short(vt_symbol=self.act_vt_symbol,
|
act_vt_orderids = self.short(vt_symbol=self.act_vt_symbol,
|
||||||
price=self.cur_act_tick.bid_price1,
|
price=self.cur_act_tick.bid_price1,
|
||||||
volume=grid.volume * self.act_vol_ratio,
|
volume=grid.volume * self.act_vol_ratio,
|
||||||
order_type=self.order_type,
|
order_type=self.order_type,
|
||||||
order_time=self.cur_datetime,
|
order_time=self.cur_datetime,
|
||||||
grid=grid)
|
grid=grid)
|
||||||
if not act_vt_orderids:
|
if not act_vt_orderids:
|
||||||
self.write_error(f'spd_short,{self.act_vt_symbol}开空仓{grid.volume * self.act_vol_ratio}手失败,'
|
self.write_error(f'spd_short,{self.act_vt_symbol}开空仓{grid.volume * self.act_vol_ratio}手失败,'
|
||||||
f'委托价:{self.cur_act_tick.bid_price1}')
|
f'委托价:{self.cur_act_tick.bid_price1}')
|
||||||
@ -987,11 +988,11 @@ class CtaSpreadTemplate(CtaTemplate):
|
|||||||
|
|
||||||
# 开多被动腿
|
# 开多被动腿
|
||||||
pas_vt_orderids = self.buy(vt_symbol=self.pas_vt_symbol,
|
pas_vt_orderids = self.buy(vt_symbol=self.pas_vt_symbol,
|
||||||
price=self.cur_pas_tick.ask_price1,
|
price=self.cur_pas_tick.ask_price1,
|
||||||
volume=grid.volume * self.pas_vol_ratio,
|
volume=grid.volume * self.pas_vol_ratio,
|
||||||
order_type=self.order_type,
|
order_type=self.order_type,
|
||||||
order_time=self.cur_datetime,
|
order_time=self.cur_datetime,
|
||||||
grid=grid)
|
grid=grid)
|
||||||
if not pas_vt_orderids:
|
if not pas_vt_orderids:
|
||||||
self.write_error(f'spd_short,{self.pas_vt_symbol}开多仓{grid.volume * self.pas_vol_ratio}手失败,'
|
self.write_error(f'spd_short,{self.pas_vt_symbol}开多仓{grid.volume * self.pas_vol_ratio}手失败,'
|
||||||
f'委托价:{self.cur_pas_tick.ask_price1}')
|
f'委托价:{self.cur_pas_tick.ask_price1}')
|
||||||
@ -1034,11 +1035,11 @@ class CtaSpreadTemplate(CtaTemplate):
|
|||||||
|
|
||||||
# 开多主动腿
|
# 开多主动腿
|
||||||
act_vt_orderids = self.buy(vt_symbol=self.act_vt_symbol,
|
act_vt_orderids = self.buy(vt_symbol=self.act_vt_symbol,
|
||||||
price=self.cur_act_tick.ask_price1,
|
price=self.cur_act_tick.ask_price1,
|
||||||
volume=grid.volume * self.act_vol_ratio,
|
volume=grid.volume * self.act_vol_ratio,
|
||||||
order_type=self.order_type,
|
order_type=self.order_type,
|
||||||
order_time=self.cur_datetime,
|
order_time=self.cur_datetime,
|
||||||
grid=grid)
|
grid=grid)
|
||||||
if not act_vt_orderids:
|
if not act_vt_orderids:
|
||||||
self.write_error(f'spd_short,{self.act_vt_symbol}开多仓{grid.volume * self.act_vol_ratio}手失败,'
|
self.write_error(f'spd_short,{self.act_vt_symbol}开多仓{grid.volume * self.act_vol_ratio}手失败,'
|
||||||
f'委托价:{self.cur_act_tick.ask_price1}')
|
f'委托价:{self.cur_act_tick.ask_price1}')
|
||||||
@ -1046,11 +1047,11 @@ class CtaSpreadTemplate(CtaTemplate):
|
|||||||
|
|
||||||
# 开空被动腿
|
# 开空被动腿
|
||||||
pas_vt_orderids = self.short(vt_symbol=self.pas_vt_symbol,
|
pas_vt_orderids = self.short(vt_symbol=self.pas_vt_symbol,
|
||||||
price=self.cur_pas_tick.bid_price1,
|
price=self.cur_pas_tick.bid_price1,
|
||||||
volume=grid.volume * self.pas_vol_ratio,
|
volume=grid.volume * self.pas_vol_ratio,
|
||||||
order_type=self.order_type,
|
order_type=self.order_type,
|
||||||
order_time=self.cur_datetime,
|
order_time=self.cur_datetime,
|
||||||
grid=grid)
|
grid=grid)
|
||||||
if not pas_vt_orderids:
|
if not pas_vt_orderids:
|
||||||
self.write_error(f'spd_short,{self.pas_vt_symbol}开空仓{grid.volume * self.pas_vol_ratio}手失败,'
|
self.write_error(f'spd_short,{self.pas_vt_symbol}开空仓{grid.volume * self.pas_vol_ratio}手失败,'
|
||||||
f'委托价:{self.cur_pas_tick.bid_price1}')
|
f'委托价:{self.cur_pas_tick.bid_price1}')
|
||||||
@ -1105,11 +1106,11 @@ class CtaSpreadTemplate(CtaTemplate):
|
|||||||
|
|
||||||
# 主动腿多单平仓
|
# 主动腿多单平仓
|
||||||
act_vt_orderids = self.sell(vt_symbol=self.act_vt_symbol,
|
act_vt_orderids = self.sell(vt_symbol=self.act_vt_symbol,
|
||||||
price=self.cur_act_tick.bid_price1,
|
price=self.cur_act_tick.bid_price1,
|
||||||
volume=grid.volume * self.act_vol_ratio,
|
volume=grid.volume * self.act_vol_ratio,
|
||||||
order_type=self.order_type,
|
order_type=self.order_type,
|
||||||
order_time=self.cur_datetime,
|
order_time=self.cur_datetime,
|
||||||
grid=grid)
|
grid=grid)
|
||||||
if not act_vt_orderids:
|
if not act_vt_orderids:
|
||||||
self.write_error(f'spd_sell,{self.act_vt_symbol}多单平仓{grid.volume * self.act_vol_ratio}手失败,'
|
self.write_error(f'spd_sell,{self.act_vt_symbol}多单平仓{grid.volume * self.act_vol_ratio}手失败,'
|
||||||
f'委托价:{self.cur_act_tick.bid_price1}')
|
f'委托价:{self.cur_act_tick.bid_price1}')
|
||||||
@ -1117,11 +1118,11 @@ class CtaSpreadTemplate(CtaTemplate):
|
|||||||
|
|
||||||
# 被动腿空单平仓
|
# 被动腿空单平仓
|
||||||
pas_vt_orderids = self.cover(vt_symbol=self.pas_vt_symbol,
|
pas_vt_orderids = self.cover(vt_symbol=self.pas_vt_symbol,
|
||||||
price=self.cur_pas_tick.ask_price1,
|
price=self.cur_pas_tick.ask_price1,
|
||||||
volume=grid.volume * self.pas_vol_ratio,
|
volume=grid.volume * self.pas_vol_ratio,
|
||||||
order_type=self.order_type,
|
order_type=self.order_type,
|
||||||
order_time=self.cur_datetime,
|
order_time=self.cur_datetime,
|
||||||
grid=grid)
|
grid=grid)
|
||||||
if not pas_vt_orderids:
|
if not pas_vt_orderids:
|
||||||
self.write_error(f'spd_sell,{self.pas_vt_symbol}空单平仓{grid.volume * self.pas_vol_ratio}手失败,'
|
self.write_error(f'spd_sell,{self.pas_vt_symbol}空单平仓{grid.volume * self.pas_vol_ratio}手失败,'
|
||||||
f'委托价:{self.cur_pas_tick.ask_price1}')
|
f'委托价:{self.cur_pas_tick.ask_price1}')
|
||||||
@ -1181,11 +1182,11 @@ class CtaSpreadTemplate(CtaTemplate):
|
|||||||
|
|
||||||
# 被动腿多单平仓
|
# 被动腿多单平仓
|
||||||
pas_vt_orderids = self.sell(vt_symbol=self.pas_vt_symbol,
|
pas_vt_orderids = self.sell(vt_symbol=self.pas_vt_symbol,
|
||||||
price=self.cur_pas_tick.bid_price1,
|
price=self.cur_pas_tick.bid_price1,
|
||||||
volume=grid.volume * self.pas_vol_ratio,
|
volume=grid.volume * self.pas_vol_ratio,
|
||||||
order_type=self.order_type,
|
order_type=self.order_type,
|
||||||
order_time=self.cur_datetime,
|
order_time=self.cur_datetime,
|
||||||
grid=grid)
|
grid=grid)
|
||||||
if not pas_vt_orderids:
|
if not pas_vt_orderids:
|
||||||
self.write_error(f'spd_cover,{self.pas_vt_symbol}多单平仓{grid.volume * self.pas_vol_ratio}手失败,'
|
self.write_error(f'spd_cover,{self.pas_vt_symbol}多单平仓{grid.volume * self.pas_vol_ratio}手失败,'
|
||||||
f'委托价:{self.cur_pas_tick.bid_price1}')
|
f'委托价:{self.cur_pas_tick.bid_price1}')
|
||||||
|
0
vnpy/component/__init__.py
Normal file
0
vnpy/component/__init__.py
Normal file
72
vnpy/component/base.py
Normal file
72
vnpy/component/base.py
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
"""
|
||||||
|
定义appc常使用的基础组件
|
||||||
|
"""
|
||||||
|
import sys
|
||||||
|
from abc import ABC
|
||||||
|
from enum import Enum
|
||||||
|
from logging import INFO, ERROR
|
||||||
|
|
||||||
|
|
||||||
|
class Area(Enum):
|
||||||
|
""" Kline area """
|
||||||
|
LONG_A = 'LONG_A'
|
||||||
|
LONG_B = 'LONG_B'
|
||||||
|
LONG_C = 'LONG_C'
|
||||||
|
LONG_D = 'LONG_D'
|
||||||
|
LONG_E = 'LONG_E'
|
||||||
|
SHORT_A = 'SHORT_A'
|
||||||
|
SHORT_B = 'SHORT_B'
|
||||||
|
SHORT_C = 'SHORT_C'
|
||||||
|
SHORT_D = 'SHORT_D'
|
||||||
|
SHORT_E = 'SHORT_E'
|
||||||
|
|
||||||
|
|
||||||
|
# 各类商品所在市场,underly_symbol: price_tick
|
||||||
|
# 上期所夜盘,9:00~10:15, 10:30~11:30, 13:30~15:00, 21:00 ~2:30
|
||||||
|
NIGHT_MARKET_SQ1 = {'AU': 0.05, 'AG': 1, 'SC': 0.1}
|
||||||
|
# 上期所夜盘,9:00~10:15, 10:30~11:30, 13:30~15:00, 21:00 ~1:00
|
||||||
|
NIGHT_MARKET_SQ2 = {'CU': 10, 'PB': 5, 'AL': 5, 'ZN': 5, 'WR': 1, 'NI': 10}
|
||||||
|
# 上期所夜盘,9:00~10:15, 10:30~11:30, 13:30~15:00, 21:00 ~23:00
|
||||||
|
NIGHT_MARKET_SQ3 = {'RU': 5, 'RB': 1, 'HC': 1, 'SP': 2, 'FU': 1, 'BU': 2, 'NR': 5, 'C': 1, 'CS': 1}
|
||||||
|
# 郑商所夜盘,9:00~10:15, 10:30~11:30, 13:30~15:00, 21:00 ~23:00
|
||||||
|
NIGHT_MARKET_ZZ = {'TA': 2, 'JR': 1, 'OI': 0, 'RO': 1, 'PM': 1, 'WH': 1, 'CF': 5, 'SR': 0, 'FG': 1,
|
||||||
|
'MA': 1, 'RS': 1, 'RM': 1, 'RI': 1, 'ZC': 0.2}
|
||||||
|
# 大商所夜盘,9:00~10:15, 10:30~11:30, 13:30~15:00, 21:00 ~23:00
|
||||||
|
NIGHT_MARKET_DL = {'V': 5, 'L': 5, 'BB': 0.05, 'I': 0.5, 'FB': 0.05, 'C': 1, 'PP': 1, 'A': 1, 'B': 1, 'M': 1, 'Y': 2,
|
||||||
|
'P': 2,
|
||||||
|
'JM': 0.5, 'J': 0.5, 'EG': 1}
|
||||||
|
# 中金日盘,9:15 ~11:30, 13:00~15:15
|
||||||
|
MARKET_ZJ = {'IC': 0.2, 'IF': 0.2, 'IH': 0.2, 'T': 0.005, 'TF': 0.005, 'TS': 0.005}
|
||||||
|
|
||||||
|
# 只有日盘得合约
|
||||||
|
MARKET_DAY_ONLY = {'IC': 0.2, 'IF': 0.2, 'IH': 0.2, 'T': 0.005, 'TF': 0.005, 'TS': 0.005,
|
||||||
|
'JD': 1, 'BB': 0.05, 'CS': 1, 'FB': 0.05, 'L': 5, 'V': 5,
|
||||||
|
'JR': 1, 'LR': 1, 'PM': 1, 'RI': 1, 'RS': 1, 'SM': 2, 'WH': 1, 'AP': 1, 'CJ': 1, 'UR': 1}
|
||||||
|
|
||||||
|
# 夜盘23:00收盘的合约
|
||||||
|
NIGHT_MARKET_23 = {**NIGHT_MARKET_DL, **NIGHT_MARKET_ZZ, **NIGHT_MARKET_SQ3}
|
||||||
|
|
||||||
|
|
||||||
|
class CtaComponent(ABC):
|
||||||
|
""" CTA策略基础组件"""
|
||||||
|
|
||||||
|
def __init__(self, strategy=None, **kwargs):
|
||||||
|
"""
|
||||||
|
构造
|
||||||
|
:param strategy:
|
||||||
|
"""
|
||||||
|
self.strategy = strategy
|
||||||
|
|
||||||
|
def write_log(self, content: str):
|
||||||
|
"""记录日志"""
|
||||||
|
if self.strategy:
|
||||||
|
self.strategy.write_log(msg=content, level=INFO)
|
||||||
|
else:
|
||||||
|
print(content)
|
||||||
|
|
||||||
|
def write_error(self, content: str, level: int = ERROR):
|
||||||
|
"""记录错误日志"""
|
||||||
|
if self.strategy:
|
||||||
|
self.strategy.write_log(msg=content, level=level)
|
||||||
|
else:
|
||||||
|
print(content, file=sys.stderr)
|
@ -10,7 +10,7 @@ import traceback
|
|||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from vnpy.trader.utility import get_folder_path
|
from vnpy.trader.utility import get_folder_path
|
||||||
from vnpy.app.cta_strategy_pro.base import Direction, CtaComponent
|
from vnpy.component.base import Direction, CtaComponent
|
||||||
|
|
||||||
"""
|
"""
|
||||||
网格交易,用于套利单
|
网格交易,用于套利单
|
@ -16,17 +16,16 @@ import csv
|
|||||||
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
from pykalman import KalmanFilter
|
from pykalman import KalmanFilter
|
||||||
|
|
||||||
from vnpy.app.cta_strategy_pro.base import (
|
from vnpy.component.base import (
|
||||||
Direction,
|
Direction,
|
||||||
Area,
|
Area,
|
||||||
MARKET_DAY_ONLY,
|
MARKET_DAY_ONLY,
|
||||||
NIGHT_MARKET_23,
|
NIGHT_MARKET_23,
|
||||||
NIGHT_MARKET_SQ2,
|
NIGHT_MARKET_SQ2,
|
||||||
MARKET_ZJ)
|
MARKET_ZJ)
|
||||||
from vnpy.app.cta_strategy_pro.cta_period import CtaPeriod, Period
|
from vnpy.component.cta_period import CtaPeriod, Period
|
||||||
from vnpy.trader.object import BarData, TickData
|
from vnpy.trader.object import BarData, TickData
|
||||||
from vnpy.trader.constant import Interval, Color
|
from vnpy.trader.constant import Interval, Color
|
||||||
from vnpy.trader.utility import round_to, get_trading_date, get_underlying_symbol
|
from vnpy.trader.utility import round_to, get_trading_date, get_underlying_symbol
|
@ -20,15 +20,15 @@ class CtaPeriod(object):
|
|||||||
|
|
||||||
def __init__(self, mode: Period, price: float, pre_mode: Period = Period.INIT, dt: datetime = None):
|
def __init__(self, mode: Period, price: float, pre_mode: Period = Period.INIT, dt: datetime = None):
|
||||||
"""初始化函数"""
|
"""初始化函数"""
|
||||||
self.open = price # 开始价格
|
self.open = price # 开始价格
|
||||||
self.close = price # 结束价格
|
self.close = price # 结束价格
|
||||||
self.high = price # 最高价格
|
self.high = price # 最高价格
|
||||||
self.low = price # 最低价格
|
self.low = price # 最低价格
|
||||||
|
|
||||||
self.mode = mode # 周期模式 XXX
|
self.mode = mode # 周期模式 XXX
|
||||||
self.pre_mode = pre_mode # 上一周期
|
self.pre_mode = pre_mode # 上一周期
|
||||||
|
|
||||||
self.datetime = dt if dt else datetime.now() # 周期的开始时间
|
self.datetime = dt if dt else datetime.now() # 周期的开始时间
|
||||||
|
|
||||||
def update_price(self, price):
|
def update_price(self, price):
|
||||||
"""更新周期的价格"""
|
"""更新周期的价格"""
|
@ -4,7 +4,7 @@ import os
|
|||||||
import json
|
import json
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from vnpy.app.cta_strategy_pro.base import CtaComponent
|
from vnpy.component.base import CtaComponent
|
||||||
from vnpy.trader.utility import get_folder_path
|
from vnpy.trader.utility import get_folder_path
|
||||||
|
|
||||||
TNS_STATUS_OBSERVATE = 'observate'
|
TNS_STATUS_OBSERVATE = 'observate'
|
@ -1,8 +1,7 @@
|
|||||||
# encoding: UTF-8
|
# encoding: UTF-8
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
from vnpy.component.base import Direction, CtaComponent
|
||||||
from vnpy.app.cta_strategy_pro.base import Direction, CtaComponent
|
|
||||||
|
|
||||||
|
|
||||||
class CtaPosition(CtaComponent):
|
class CtaPosition(CtaComponent):
|
@ -17,7 +17,7 @@ os.environ["VNPY_TESTING"] = "1"
|
|||||||
from vnpy.trader.constant import Interval, Exchange
|
from vnpy.trader.constant import Interval, Exchange
|
||||||
from vnpy.data.tdx.tdx_common import FakeStrategy
|
from vnpy.data.tdx.tdx_common import FakeStrategy
|
||||||
from vnpy.data.tdx.tdx_future_data import TdxFutureData
|
from vnpy.data.tdx.tdx_future_data import TdxFutureData
|
||||||
from vnpy.app.cta_strategy_pro.cta_line_bar import CtaLineBar
|
from vnpy.component.cta_line_bar import CtaLineBar
|
||||||
from vnpy.trader.object import TickData
|
from vnpy.trader.object import TickData
|
||||||
from vnpy.trader.utility import get_trading_date
|
from vnpy.trader.utility import get_trading_date
|
||||||
|
|
@ -18,7 +18,7 @@ os.environ["VNPY_TESTING"] = "1"
|
|||||||
|
|
||||||
from vnpy.trader.constant import Interval, Exchange
|
from vnpy.trader.constant import Interval, Exchange
|
||||||
from vnpy.trader.object import BarData
|
from vnpy.trader.object import BarData
|
||||||
from vnpy.app.cta_strategy_pro.cta_line_bar import (
|
from vnpy.component.cta_line_bar import (
|
||||||
CtaLineBar,
|
CtaLineBar,
|
||||||
CtaMinuteBar,
|
CtaMinuteBar,
|
||||||
CtaHourBar,
|
CtaHourBar,
|
@ -118,6 +118,7 @@ class RenkoBarData(BarData):
|
|||||||
low_time = None # 最后一次进入低位区域的时间
|
low_time = None # 最后一次进入低位区域的时间
|
||||||
high_time = None # 最后一次进入高位区域的时间
|
high_time = None # 最后一次进入高位区域的时间
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class OrderData(BaseData):
|
class OrderData(BaseData):
|
||||||
"""
|
"""
|
||||||
|
@ -246,7 +246,7 @@ def get_icon_path(filepath: str, ico_name: str):
|
|||||||
return str(icon_path)
|
return str(icon_path)
|
||||||
|
|
||||||
|
|
||||||
def load_json(filename: str, auto_save : bool = True):
|
def load_json(filename: str, auto_save: bool = True):
|
||||||
"""
|
"""
|
||||||
Load data from json file in temp path.
|
Load data from json file in temp path.
|
||||||
"""
|
"""
|
||||||
|
Loading…
Reference in New Issue
Block a user