- 策略广场
- 生猪基差回归套利策略
生猪基差回归套利策略
Author:
ianzeng123, Date: 2024-04-24 11:34:09
Tags:
import json
class TradingStrategy:
def __init__(self, pigPeriod, pigWidth):
self.cfgA = {
"extension": {
"layout": 'single',
"col": 6,
"height": "500px",
},
"title": {
"text": "期现图表"
},
"xAxis": {
"type": "datetime"
},
"series": [{
"name": "期货价格",
"data": [17300.0, 17695.0, 17590.0, 17780.0, 17780.0, 18070.0, 17990.0, 18175.0, 18200.0, 18055.0, 18100.0, 18255.0, 18250.0, 18110.0, 18300.0, 18470.0, 18155.0, 18225.0, 18305.0, 18225.0, 17930.0, 17980.0, 17890.0, 17965.0, 18280.0, 18305.0, 18185.0, 18155.0, 18210.0, 17960.0, 18140.0, 18385.0, 18210.0, 17900.0, 17880.0, 17880.0, 17625.0, 17580.0, 17630.0, 17540.0, 17475.0, 17300.0, 17495.0, 17285.0, 17580.0, 17630.0, 17620.0, 17560.0, 17660.0, 17795.0, 17860.0, 17855.0, 17845.0, 17980.0, 17930.0, 18010.0, 17580.0, 17900.0],
}, {
"name": "现货价格",
"data": [14880, 14870, 14870, 14880, 14880, 14880, 14930, 14970, 15050, 15150, 15230, 15230, 15450, 15570, 15670, 15900, 16230, 16230, 16600, 16900, 16900, 17430, 17420, 17420, 17600, 17800, 18000, 18020, 18100, 18100, 18350, 18530, 18600, 18600, 18600, 18600, 18570, 18520, 18380, 18330, 18330, 18030, 17720, 17630, 17630, 17630, 17630, 17900, 17880, 17950, 18050, 18270, 18270, 18320, 18430, 18500, 18500, 18500],
}]
}
self.cfgB = {
"extension": {
"layout": 'single',
"col": 6,
"height": "500px",
},
"title": {
"text": "基差图表"
},
"xAxis": {
"type": "datetime"
},
"series": [{
"name": "基差价格",
"data": [-2420.0, -2825.0, -2720.0, -2900.0, -2900.0, -3190.0, -3060.0, -3205.0, -3150.0, -2905.0, -2870.0, -3025.0, -2800.0, -2540.0, -2630.0, -2570.0, -1925.0, -1995.0, -1705.0, -1325.0, -1030.0, -550.0, -470.0, -545.0, -680.0, -505.0, -185.0, -135.0, -110.0, 140.0, 210.0, 145.0, 390.0, 700.0, 720.0, 720.0, 945.0, 940.0, 750.0, 790.0, 855.0, 730.0, 225.0, 345.0, 50.0, 0.0, 10.0, 340.0, 220.0, 155.0, 190.0, 415.0, 425.0, 340.0, 500.0, 490.0, 920.0, 600.0],
}]
}
self.chart = Chart([self.cfgA, self.cfgB]) # 创建一个图表对象
# 初始化其他全局变量
self.info = []
self.basis = 0
self.spot = 0
self.basisList = [-2420.0, -2825.0, -2720.0, -2900.0, -2900.0, -3190.0, -3060.0, -3205.0, -3150.0, -2905.0, -2870.0, -3025.0, -2800.0, -2540.0, -2630.0, -2570.0, -1925.0, -1995.0, -1705.0, -1325.0, -1030.0, -550.0, -470.0, -545.0, -680.0, -505.0, -185.0, -135.0, -110.0, 140.0, 210.0, 145.0, 390.0, 700.0, 720.0, 720.0, 945.0, 940.0, 750.0, 790.0, 855.0, 730.0, 225.0, 345.0, 50.0, 0.0, 10.0, 340.0, 220.0, 155.0, 190.0, 415.0, 425.0, 340.0, 500.0, 490.0, 920.0, 600.0]
self.holdprice = '-'
self.holddir = '-'
self.holdprofit = 0
self.pos = []
self.pre_data = []
self.pigPeriod = pigPeriod
self.pigWidth = pigWidth
self.initAccount = _C(exchange.GetAccount) # 获取初始账户信息
def update_spot_and_basis(self, futures_price):
obj = exchange.GetData("https://www.datadata.cn/api/v1/query/94af6e1e-2efa-4e0c-8c08-f7853b2bf969/data")
if obj["Data"] != self.pre_data:
self.pre_data = obj["Data"]
self.info = json.loads(obj["Data"])
self.spot = self.info['spot_price']
self.basis = self.spot - futures_price
self.basisList.append(self.basis)
def plot_data(self, futures_ts, futures_price):
self.chart.add(0, [futures_ts, futures_price]) # 绘制期货价格
self.chart.add(1, [futures_ts, self.spot]) # 绘制现货价格
self.chart.add(2, [futures_ts, self.basis]) # 绘制基差
self.chart.update([self.cfgA, self.cfgB]) # 更新图表
def handle_position(self, futures_price, mainid):
basisBoll = TA.BOLL(self.basisList, self.pigPeriod, self.pigWidth)
p = ext.NewPositionManager()
self.pos = exchange.GetPosition()
if len(self.pos) != 0 and self.pos[0].ContractType != mainid:
p.Cover(self.pos[0].ContractType)
Log('今日主力合约:', mainid, '平旧仓: ', self.pos[0].ContractType, '#FFA500')
self.basisList = [] # 重新开始计算基差
if len(self.basisList) < self.pigPeriod + 2:
return
if self.basis > basisBoll[0][-2] and len(self.pos) == 0:
Log('基差上限:', basisBoll[0][-2], '基差下限:', basisBoll[2][-2], '当今基差:', self.basis)
Log('基差过大,期货开多仓', '#ff0000')
p.OpenLong(mainid, 1)
if len(self.pos) == 1 and self.pos[0].Type == 0 and (self.basis < basisBoll[1][-2]):
Log('基差上限:', basisBoll[0][-2], '基差下限:', basisBoll[2][-2], '当今基差:', self.basis)
Log('基差回归,期货平仓', '#0000ff')
p.Cover(mainid)
if self.basis < basisBoll[2][-2] and len(self.pos) == 0:
Log('基差上限:', basisBoll[0][-2], '基差下限:', basisBoll[2][-2], '当今基差:', self.basis)
Log('基差过小,期货开空仓', '#00ff00')
p.OpenShort(mainid, 1)
if len(self.pos) == 1 and self.pos[0].Type == 1 and (self.basis > basisBoll[1][-2]):
Log('基差上限:', basisBoll[0][-2], '基差下限:', basisBoll[2][-2], '当今基差:', self.basis)
Log('基差回归,期货平仓', '#0000ff')
p.Cover(mainid)
def update_status_table(self, futures_price):
positions = _C(exchange.GetPosition)
tblStatus = {
"type": "table",
"title": "策略状态",
"cols": ["现货价格", "期货价格", "基差", "持仓均价", "持仓方向", "持仓盈亏"],
"rows": []
}
if len(positions) != 0:
self.holdprice = positions[0].Price
self.holddir = '多头' if positions[0].Type == 0 else '空头'
self.holdprofit = (futures_price - positions[0].Price) * 16 if positions[0].Type == 0 else (futures_price - positions[0].Price) * -16
else:
self.holdprice = 0
self.holddir = '-'
self.holdprofit = '-'
tblStatus["rows"].append([self.spot, futures_price, self.basis, self.holdprice, self.holddir, self.holdprofit])
return tblStatus
def log_profit_and_status(self, futures_price):
cur_time = int(_D()[0:10].replace("-", "")) # 获取当前日级别时间
curAccount = _C(exchange.GetAccount)
curProfit = float(curAccount.Info.Balance) - float(self.initAccount.Info.Balance)
LogProfit(curProfit, "&")
tblStatus = self.update_status_table(futures_price)
lastStatus = f"`{json.dumps(tblStatus)}`\n当前时间: {cur_time}"
LogStatus(lastStatus)
def onTick(self):
maininfo = _C(exchange.SetContractType, "lh888") # 订阅期货品种
mainid = maininfo['InstrumentID']
futures = _C(exchange.GetRecords)[-1] # 获取最新K线数据
futures_ts = futures.Time # 获取最新K线期货时间戳
futures_price = futures.Close # 获取最新K线收盘价
self.update_spot_and_basis(futures_price)
self.plot_data(futures_ts, futures_price)
self.handle_position(futures_price, mainid)
self.log_profit_and_status(futures_price)
def main():
SetErrorFilter("502:|503:|tcp|character|unexpected|network|timeout|WSARecv|Connect|GetAddr|no such|reset|http|received|EOF|reused|(CTP_T@10010)|Futures_OP 3: not login")
strategy = TradingStrategy(pigPeriod, pigWidth)
LogReset() # 运行前先清空之前的Log日志信息
strategy.chart.reset() # 运行前先清空之前的图表信息
while True: # 进入循环模式
if exchange.IO('status'):
strategy.onTick() # 执行策略主函数
Sleep(1000 * 60 * 60 * 24) # 策略休眠一天
更多内容