Sunteți pe pagina 1din 26

CTA策略略模块 10/2/19, 1(07 AM

http://www.vnpy.com/docs/cn/cta_strategy.html#id2 Page 1 of 26
CTA策略略模块 10/2/19, 1(07 AM

def init_rqdata(self):
"""
Init RQData client.
"""
username = SETTINGS["rqdata.username"]
password = SETTINGS["rqdata.password"]
if not username or not password:
return

import rqdatac

self.rq_client = rqdatac
self.rq_client.init(username, password,
('rqdatad-pro.ricequant.com', 16011))

http://www.vnpy.com/docs/cn/cta_strategy.html#id2 Page 2 of 26
CTA策略略模块 10/2/19, 1(07 AM

def query_bar_from_rq(
self, vt_symbol: str, interval: Interval, start: datetime, end:
datetime
):
"""
Query bar data from RQData.
"""
symbol, exchange_str = vt_symbol.split(".")
rq_symbol = to_rq_symbol(vt_symbol)
if rq_symbol not in self.rq_symbols:
return None

end += timedelta(1) # For querying night trading period dat


a

df = self.rq_client.get_price(
rq_symbol,
frequency=interval.value,
fields=["open", "high", "low", "close", "volume"],
start_date=start,
end_date=end
)

data = []
for ix, row in df.iterrows():
bar = BarData(
symbol=symbol,
exchange=Exchange(exchange_str),
interval=interval,
datetime=row.name.to_pydatetime(),
open_price=row["open"],
high_price=row["high"],
low_price=row["low"],
close_price=row["close"],
volume=row["volume"],
gateway_name="RQ"
)
data.append(bar)

http://www.vnpy.com/docs/cn/cta_strategy.html#id2 Page 3 of 26
CTA策略略模块 10/2/19, 1(07 AM

boll_window = 18
boll_dev = 3.4
cci_window = 10
atr_window = 30
sl_multiplier = 5.2
fixed_size = 1

boll_up = 0
boll_down = 0
cci_value = 0
atr_value = 0

intra_trade_high = 0
intra_trade_low = 0
long_stop = 0
short_stop = 0

def __init__(self, cta_engine, strategy_name, vt_symbol, setting):


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

self.bg = BarGenerator(self.on_bar, 15, self.on_15min_bar)


self.am = ArrayManager()

http://www.vnpy.com/docs/cn/cta_strategy.html#id2 Page 4 of 26
CTA策略略模块 10/2/19, 1(07 AM

def on_init(self):
"""
Callback when strategy is inited.
"""
self.write_log(" ")
self.load_bar(10)

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

def on_stop(self):
"""
Callback when strategy is stopped.
"""
self.write_log(" ")

def on_tick(self, tick: TickData):


"""
Callback of new tick data update.
"""
self.bg.update_tick(tick)

def on_bar(self, bar: BarData):


"""
Callback of new bar data update.
"""
self.bg.update_bar(bar)

http://www.vnpy.com/docs/cn/cta_strategy.html#id2 Page 5 of 26
CTA策略略模块 10/2/19, 1(07 AM

def on_15min_bar(self, bar: BarData):


""""""
self.cancel_all()

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

self.boll_up, self.boll_down = am.boll(self.boll_window, self.b


oll_dev)
self.cci_value = am.cci(self.cci_window)
self.atr_value = am.atr(self.atr_window)

if self.pos == 0:
self.intra_trade_high = bar.high_price
self.intra_trade_low = bar.low_price

if self.cci_value > 0:
self.buy(self.boll_up, self.fixed_size, True)
elif self.cci_value < 0:
self.short(self.boll_down, self.fixed_size, True)

elif self.pos > 0:


self.intra_trade_high = max(self.intra_trade_high, bar.high
_price)
self.intra_trade_low = bar.low_price

self.long_stop = self.intra_trade_high - self.atr_value * s


elf.sl_multiplier
self.sell(self.long_stop, abs(self.pos), True)

elif self.pos < 0:


self.intra_trade_high = bar.high_price
self.intra_trade_low = min(self.intra_trade_low, bar.low_pr
ice)

self.short_stop = self.intra_trade_low + self.atr_value * s


elf.sl_multiplier
self.cover(self.short_stop, abs(self.pos), True)

self.put_event()

http://www.vnpy.com/docs/cn/cta_strategy.html#id2 Page 6 of 26
CTA策略略模块 10/2/19, 1(07 AM

def on_order(self, order: OrderData):


"""
Callback of new order data update.
"""
pass

def on_trade(self, trade: TradeData):


"""
Callback of new trade data update.
"""
self.put_event()

def on_stop_order(self, stop_order: StopOrder):


"""
Callback of stop order update.
"""
pass

def add_strategy(self, strategy_class: type, setting: dict):


""""""
self.strategy_class = strategy_class
self.strategy = strategy_class(
self, strategy_class.__name__, self.vt_symbol, setting
)

http://www.vnpy.com/docs/cn/cta_strategy.html#id2 Page 7 of 26
CTA策略略模块 10/2/19, 1(07 AM

def load_data(self):
""""""
self.output(" ")

if self.mode == BacktestingMode.BAR:
s = (
DbBarData.select()
.where(
(DbBarData.vt_symbol == self.vt_symbol)
& (DbBarData.interval == self.interval)
& (DbBarData.datetime >= self.start)
& (DbBarData.datetime <= self.end)
)
.order_by(DbBarData.datetime)
)
self.history_data = [db_bar.to_bar() for db_bar in s]
else:
s = (
DbTickData.select()
.where(
(DbTickData.vt_symbol == self.vt_symbol)
& (DbTickData.datetime >= self.start)
& (DbTickData.datetime <= self.end)
)
.order_by(DbTickData.datetime)
)
self.history_data = [db_tick.to_tick() for db_tick in s]

self.output(f" {len(self.history_data)}")

def cross_limit_order(self):
"""
Cross limit order with last bar/tick data.

http://www.vnpy.com/docs/cn/cta_strategy.html#id2 Page 8 of 26
CTA策略略模块 10/2/19, 1(07 AM

"""
if self.mode == BacktestingMode.BAR:
long_cross_price = self.bar.low_price
short_cross_price = self.bar.high_price
long_best_price = self.bar.open_price
short_best_price = self.bar.open_price
else:
long_cross_price = self.tick.ask_price_1
short_cross_price = self.tick.bid_price_1
long_best_price = long_cross_price
short_best_price = short_cross_price

for order in list(self.active_limit_orders.values()):


# Push order update with status "not traded" (pending)
if order.status == Status.SUBMITTING:
order.status = Status.NOTTRADED
self.strategy.on_order(order)

# Check whether limit orders can be filled.


long_cross = (
order.direction == Direction.LONG
and order.price >= long_cross_price
and long_cross_price > 0
)

short_cross = (
order.direction == Direction.SHORT
and order.price <= short_cross_price
and short_cross_price > 0
)

if not long_cross and not short_cross:


continue

# Push order udpate with status "all traded" (filled).


order.traded = order.volume
order.status = Status.ALLTRADED
self.strategy.on_order(order)

self.active_limit_orders.pop(order.vt_orderid)

# Push trade update


self.trade_count += 1

if long_cross:
trade_price = min(order.price, long_best_price)
pos_change = order.volume
else:
trade_price = max(order.price, short_best_price)
pos_change = -order.volume

trade = TradeData(
symbol=order.symbol,
exchange=order.exchange,
orderid=order.orderid,
tradeid=str(self.trade_count),
direction=order.direction,
offset=order.offset,
price=trade_price,
volume=order.volume,
time=self.datetime.strftime("%H:%M:%S"),
gateway_name=self.gateway_name,
)
trade.datetime = self.datetime

http://www.vnpy.com/docs/cn/cta_strategy.html#id2 Page 9 of 26
CTA策略略模块 10/2/19, 1(07 AM

self.strategy.pos += pos_change
self.strategy.on_trade(trade)

self.trades[trade.vt_tradeid] = trade

def calculate_pnl(
self,
pre_close: float,
start_pos: float,
size: int,
rate: float,
slippage: float,
):
""""""
self.pre_close = pre_close

# Holding pnl is the pnl from holding position at day start


self.start_pos = start_pos
self.end_pos = start_pos
self.holding_pnl = self.start_pos * \
(self.close_price - self.pre_close) * size

# Trading pnl is the pnl from new trade during the day
self.trade_count = len(self.trades)

for trade in self.trades:


if trade.direction == Direction.LONG:
pos_change = trade.volume
else:
pos_change = -trade.volume

turnover = trade.price * trade.volume * size

self.trading_pnl += pos_change * \
(self.close_price - trade.price) * size
self.end_pos += pos_change
self.turnover += turnover
self.commission += turnover * rate
self.slippage += trade.volume * size * slippage

# Net pnl takes account of commission and slippage cost


self.total_pnl = self.trading_pnl + self.holding_pnl
self.net_pnl = self.total_pnl - self.commission - self.slippage

http://www.vnpy.com/docs/cn/cta_strategy.html#id2 Page 10 of 26
CTA策略略模块 10/2/19, 1(07 AM

df["balance"] = df["net_pnl"].cumsum() + self.capital


df["return"] = np.log(df["balance"] / df["balance"].shift(1
)).fillna(0)
df["highlevel"] = (
df["balance"].rolling(
min_periods=1, window=len(df), center=False).max()
)
df["drawdown"] = df["balance"] - df["highlevel"]
df["ddpercent"] = df["drawdown"] / df["highlevel"] * 100

# Calculate statistics value


start_date = df.index[0]
end_date = df.index[-1]

total_days = len(df)
profit_days = len(df[df["net_pnl"] > 0])
loss_days = len(df[df["net_pnl"] < 0])

end_balance = df["balance"].iloc[-1]
max_drawdown = df["drawdown"].min()
max_ddpercent = df["ddpercent"].min()

total_net_pnl = df["net_pnl"].sum()
daily_net_pnl = total_net_pnl / total_days

total_commission = df["commission"].sum()
daily_commission = total_commission / total_days

total_slippage = df["slippage"].sum()
daily_slippage = total_slippage / total_days

total_turnover = df["turnover"].sum()
daily_turnover = total_turnover / total_days

total_trade_count = df["trade_count"].sum()
daily_trade_count = total_trade_count / total_days

total_return = (end_balance / self.capital - 1) * 100


annual_return = total_return / total_days * 240
daily_return = df["return"].mean() * 100
return_std = df["return"].std() * 100

if return_std:
sharpe_ratio = daily_return / return_std * np.sqrt(240)
else:
sharpe_ratio = 0

http://www.vnpy.com/docs/cn/cta_strategy.html#id2 Page 11 of 26
CTA策略略模块 10/2/19, 1(07 AM

def show_chart(self, df: DataFrame = None):


""""""
if not df:
df = self.daily_df

if df is None:
return

plt.figure(figsize=(10, 16))

balance_plot = plt.subplot(4, 1, 1)
balance_plot.set_title("Balance")
df["balance"].plot(legend=True)

drawdown_plot = plt.subplot(4, 1, 2)
drawdown_plot.set_title("Drawdown")
drawdown_plot.fill_between(range(len(df)), df["drawdown"].value
s)

pnl_plot = plt.subplot(4, 1, 3)
pnl_plot.set_title("Daily Pnl")
df["net_pnl"].plot(kind="bar", legend=False, grid=False, xticks
=[])

distribution_plot = plt.subplot(4, 1, 4)
distribution_plot.set_title("Daily Pnl Distribution")
df["net_pnl"].hist(bins=50)

plt.show()

http://www.vnpy.com/docs/cn/cta_strategy.html#id2 Page 12 of 26
CTA策略略模块 10/2/19, 1(07 AM

from vnpy.app.cta_strategy.backtesting import BacktestingEngine


from vnpy.app.cta_strategy.strategies.boll_channel_strategy import (
BollChannelStrategy,
)
from datetime import datetime

engine = BacktestingEngine()
engine.set_parameters(
vt_symbol="IF88.CFFEX",
interval="1m",
start=datetime(2018, 1, 1),
end=datetime(2019, 1, 1),
rate=3.0/10000,
slippage=0.2,
size=300,
pricetick=0.2,
capital=1_000_000,
)

engine.add_strategy(AtrRsiStrategy, {})
engine.load_data()
engine.run_backtesting()
df = engine.calculate_result()
engine.calculate_statistics()
engine.show_chart()

http://www.vnpy.com/docs/cn/cta_strategy.html#id2 Page 13 of 26
CTA策略略模块 10/2/19, 1(07 AM

from vnpy.app.cta_strategy.backtesting import BacktestingEngine, Optimi


zationSetting
from vnpy.app.cta_strategy.strategies.atr_rsi_strategy import AtrRsiStr
ategy
from vnpy.app.cta_strategy.strategies.boll_channel_strategy import Boll
ChannelStrategy
from datetime import datetime

def run_backtesting(strategy_class, setting, vt_symbol, interval, start


, end, rate, slippage, size, pricetick, capital):
engine = BacktestingEngine()
engine.set_parameters(
vt_symbol=vt_symbol,
interval=interval,
start=start,
end=end,
rate=rate,
slippage=slippage,
size=size,
pricetick=pricetick,
capital=capital
)
engine.add_strategy(strategy_class, setting)
engine.load_data()
engine.run_backtesting()
df = engine.calculate_result()
return df

http://www.vnpy.com/docs/cn/cta_strategy.html#id2 Page 14 of 26
CTA策略略模块 10/2/19, 1(07 AM

df1 = run_backtesting(
strategy_class=AtrRsiStrategy,
setting={},
vt_symbol="IF88.CFFEX",
interval="1m",
start=datetime(2019, 1, 1),
end=datetime(2019, 4, 30),
rate=0.3/10000,
slippage=0.2,
size=300,
pricetick=0.2,
capital=1_000_000,
)

df2 = run_backtesting(
strategy_class=BollChannelStrategy,
setting={'fixed_size': 16},
vt_symbol="RB88.SHFE",
interval="1m",
start=datetime(2019, 1, 1),
end=datetime(2019, 4, 30),
rate=1/10000,
slippage=1,
size=10,
pricetick=1,
capital=1_000_000,
)

dfp = df1 + df2


dfp =dfp.dropna()

def show_portafolio(df):
engine = BacktestingEngine()
engine.calculate_statistics(df)
engine.show_chart(df)

show_portafolio(dfp)

http://www.vnpy.com/docs/cn/cta_strategy.html#id2 Page 15 of 26
CTA策略略模块 10/2/19, 1(07 AM

class OptimizationSetting:
"""
Setting for runnning optimization.
"""

def __init__(self):
""""""
self.params = {}
self.target_name = ""

def add_parameter(
self, name: str, start: float, end: float = None, step: float =
None
):
""""""
if not end and not step:
self.params[name] = [start]
return

if start >= end:


print(" ")
return

if step <= 0:
print(" 0")
return

value = start
value_list = []

while value <= end:


value_list.append(value)
value += step

self.params[name] = value_list

def set_target(self, target_name: str):


""""""
self.target_name = target_name

def generate_setting(self):
""""""
keys = self.params.keys()
values = self.params.values()
products = list(product(*values))

settings = []
for p in products:
setting = dict(zip(keys, p))
settings.append(setting)

return settings

http://www.vnpy.com/docs/cn/cta_strategy.html#id2 Page 16 of 26
CTA策略略模块 10/2/19, 1(07 AM

def optimize(
target_name: str,
strategy_class: CtaTemplate,
setting: dict,
vt_symbol: str,
interval: Interval,
start: datetime,
rate: float,
slippage: float,
size: float,
pricetick: float,
capital: int,
end: datetime,
mode: BacktestingMode,
):
"""
Function for running in multiprocessing.pool
"""
engine = BacktestingEngine()
engine.set_parameters(
vt_symbol=vt_symbol,
interval=interval,
start=start,
rate=rate,
slippage=slippage,
size=size,
pricetick=pricetick,
capital=capital,
end=end,
mode=mode
)

engine.add_strategy(strategy_class, setting)
engine.load_data()
engine.run_backtesting()
engine.calculate_result()
statistics = engine.calculate_statistics()

target_value = statistics[target_name]
return (str(setting), target_value, statistics)

http://www.vnpy.com/docs/cn/cta_strategy.html#id2 Page 17 of 26
CTA策略略模块 10/2/19, 1(07 AM

pool = multiprocessing.Pool(multiprocessing.cpu_count())

results = []
for setting in settings:
result = (pool.apply_async(optimize, (
target_name,
self.strategy_class,
setting,
self.vt_symbol,
self.interval,
self.start,
self.rate,
self.slippage,
self.size,
self.pricetick,
self.capital,
self.end,
self.mode
)))
results.append(result)

pool.close()
pool.join()

# Sort results and output


result_values = [result.get() for result in results]
result_values.sort(reverse=True, key=lambda result: result[1])

for value in result_values:


msg = f" {value[0]}, {value[1]}"
self.output(msg)

return result_values

http://www.vnpy.com/docs/cn/cta_strategy.html#id2 Page 18 of 26
CTA策略略模块 10/2/19, 1(07 AM

def add_strategy(
self, class_name: str, strategy_name: str, vt_symbol: str, sett
ing: dict
):
"""
Add a new strategy.
"""
if strategy_name in self.strategies:
self.write_log(f" {strategy_name}")
return

strategy_class = self.classes[class_name]

strategy = strategy_class(self, strategy_name, vt_symbol, setti


ng)
self.strategies[strategy_name] = strategy

# Add vt_symbol to strategy map.


strategies = self.symbol_strategy_map[vt_symbol]
strategies.append(strategy)

# Update to setting file.


self.update_strategy_setting(strategy_name, setting)

self.put_strategy_event(strategy)

http://www.vnpy.com/docs/cn/cta_strategy.html#id2 Page 19 of 26
CTA策略略模块 10/2/19, 1(07 AM

def _init_strategy(self):
"""
Init strategies in queue.
"""
while not self.init_queue.empty():
strategy_name = self.init_queue.get()
strategy = self.strategies[strategy_name]

if strategy.inited:
self.write_log(f"{strategy_name}
")
continue

self.write_log(f"{strategy_name} ")

# Call on_init function of strategy


self.call_strategy_func(strategy, strategy.on_init)

# Restore strategy data(variables)


data = self.strategy_data.get(strategy_name, None)
if data:
for name in strategy.variables:
value = data.get(name, None)
if value:
setattr(strategy, name, value)

# Subscribe market data


contract = self.main_engine.get_contract(strategy.vt_symbol
)
if contract:
req = SubscribeRequest(
symbol=contract.symbol, exchange=contract.exchange)
self.main_engine.subscribe(req, contract.gateway_name)
else:
self.write_log(f" {strategy.vt_symbo
l}", strategy)

# Put event to update init completed status.


strategy.inited = True
self.put_strategy_event(strategy)
self.write_log(f"{strategy_name} ")

self.init_thread = None

http://www.vnpy.com/docs/cn/cta_strategy.html#id2 Page 20 of 26
CTA策略略模块 10/2/19, 1(07 AM

def start_strategy(self, strategy_name: str):


"""
Start a strategy.
"""
strategy = self.strategies[strategy_name]
if not strategy.inited:
self.write_log(f" {strategy.strategy_name}
")
return

if strategy.trading:
self.write_log(f"{strategy_name} ")
return

self.call_strategy_func(strategy, strategy.on_start)
strategy.trading = True

self.put_strategy_event(strategy)

def stop_strategy(self, strategy_name: str):


"""
Stop a strategy.
"""
strategy = self.strategies[strategy_name]
if not strategy.trading:
return

# Call on_stop function of the strategy


self.call_strategy_func(strategy, strategy.on_stop)

# Change trading status of strategy to False


strategy.trading = False

# Cancel all orders of the strategy


self.cancel_all(strategy)

# Sync strategy variables to data file


self.sync_strategy_data(strategy)

# Update GUI
self.put_strategy_event(strategy)

http://www.vnpy.com/docs/cn/cta_strategy.html#id2 Page 21 of 26
CTA策略略模块 10/2/19, 1(07 AM

def edit_strategy(self, strategy_name: str, setting: dict):


"""
Edit parameters of a strategy.
"""
strategy = self.strategies[strategy_name]
strategy.update_setting(setting)

self.update_strategy_setting(strategy_name, setting)
self.put_strategy_event(strategy)

def remove_strategy(self, strategy_name: str):


"""
Remove a strategy.
"""
strategy = self.strategies[strategy_name]
if strategy.trading:
self.write_log(f" {strategy.strategy_name}
")
return

# Remove setting
self.remove_strategy_setting(strategy_name)

# Remove from symbol strategy map


strategies = self.symbol_strategy_map[strategy.vt_symbol]
strategies.remove(strategy)

# Remove from active orderid map


if strategy_name in self.strategy_orderid_map:
vt_orderids = self.strategy_orderid_map.pop(strategy_name)

# Remove vt_orderid strategy map


for vt_orderid in vt_orderids:
if vt_orderid in self.orderid_strategy_map:
self.orderid_strategy_map.pop(vt_orderid)

# Remove from strategies


self.strategies.pop(strategy_name)

return True

http://www.vnpy.com/docs/cn/cta_strategy.html#id2 Page 22 of 26
CTA策略略模块 10/2/19, 1(07 AM

def buy(self, price: float, volume: float, stop: bool = False, lock
: bool = False):
"""
Send buy order to open a long position.
"""
return self.send_order(Direction.LONG, Offset.OPEN, price, volu
me, stop, lock)

def sell(self, price: float, volume: float, stop: bool = False, loc
k: bool = False):
"""
Send sell order to close a long position.
"""
return self.send_order(Direction.SHORT, Offset.CLOSE, price, vo
lume, stop, lock)

def short(self, price: float, volume: float, stop: bool = False, lo


ck: bool = False):
"""
Send short order to open as short position.
"""
return self.send_order(Direction.SHORT, Offset.OPEN, price, vol
ume, stop, lock)

def cover(self, price: float, volume: float, stop: bool = False, lo


ck: bool = False):
"""
Send cover order to close a short position.
"""
return self.send_order(Direction.LONG, Offset.CLOSE, price, vol
ume, stop, lock)

def send_order(
self,
direction: Direction,
offset: Offset,
price: float,
volume: float,
stop: bool = False,
lock: bool = False
):
"""
Send a new order.
"""
if self.trading:
vt_orderids = self.cta_engine.send_order(
self, direction, offset, price, volume, stop, lock
)
return vt_orderids
else:
return []

http://www.vnpy.com/docs/cn/cta_strategy.html#id2 Page 23 of 26
CTA策略略模块 10/2/19, 1(07 AM

def send_order(
self,
strategy: CtaTemplate,
direction: Direction,
offset: Offset,
price: float,
volume: float,
stop: bool,
lock: bool
):
"""
"""
contract = self.main_engine.get_contract(strategy.vt_symbol)
if not contract:
self.write_log(f" {strategy.vt_symbol}", s
trategy)
return ""

if stop:
if contract.stop_supported:
return self.send_server_stop_order(strategy, contract,
direction, offset, price, volume, lock)
else:
return self.send_local_stop_order(strategy, direction,
offset, price, volume, lock)
else:
return self.send_limit_order(strategy, contract, direction,
offset, price, volume, lock)

def send_limit_order(
self,
strategy: CtaTemplate,
contract: ContractData,
direction: Direction,
offset: Offset,
price: float,
volume: float,
lock: bool
):
"""
Send a limit order to server.
"""
return self.send_server_order(
strategy,
contract,
direction,
offset,
price,
volume,
OrderType.LIMIT,
lock
)

def send_server_order(
self,
strategy: CtaTemplate,
contract: ContractData,
direction: Direction,

http://www.vnpy.com/docs/cn/cta_strategy.html#id2 Page 24 of 26
CTA策略略模块 10/2/19, 1(07 AM

offset: Offset,
price: float,
volume: float,
type: OrderType,
lock: bool
):
"""
Send a new order to server.
"""
# Create request and send order.
original_req = OrderRequest(
symbol=contract.symbol,
exchange=contract.exchange,
direction=direction,
offset=offset,
type=type,
price=price,
volume=volume,
)

# Convert with offset converter


req_list = self.offset_converter.convert_order_request(original
_req, lock)

# Send Orders
vt_orderids = []

for req in req_list:


vt_orderid = self.main_engine.send_order(
req, contract.gateway_name)
vt_orderids.append(vt_orderid)

self.offset_converter.update_order_request(req, vt_orderid)

# Save relationship between orderid and strategy.


self.orderid_strategy_map[vt_orderid] = strategy
self.strategy_orderid_map[strategy.strategy_name].add(vt_or
derid)

return vt_orderids

http://www.vnpy.com/docs/cn/cta_strategy.html#id2 Page 25 of 26
CTA策略略模块 10/2/19, 1(07 AM

def convert_order_request_lock(self, req: OrderRequest):


""""""
if req.direction == Direction.LONG:
td_volume = self.short_td
yd_available = self.short_yd - self.short_yd_frozen
else:
td_volume = self.long_td
yd_available = self.long_yd - self.long_yd_frozen

# If there is td_volume, we can only lock position


if td_volume:
req_open = copy(req)
req_open.offset = Offset.OPEN
return [req_open]
# If no td_volume, we close opposite yd position first
# then open new position
else:
open_volume = max(0, req.volume - yd_available)
req_list = []

if yd_available:
req_yd = copy(req)
if self.exchange == Exchange.SHFE:
req_yd.offset = Offset.CLOSEYESTERDAY
else:
req_yd.offset = Offset.CLOSE
req_list.append(req_yd)

if open_volume:
req_open = copy(req)
req_open.offset = Offset.OPEN
req_open.volume = open_volume
req_list.append(req_open)

return req_list

http://www.vnpy.com/docs/cn/cta_strategy.html#id2 Page 26 of 26

S-ar putea să vă placă și