增加交易策略、交易指标、量化库代码等文件夹

This commit is contained in:
Win_home committed 2025-04-27 15:54:09 +08:00
1 parent ca3b209096
commit f57150dae8
589 files changed
+854346 -1757

No files matched your search

@@ -0,0 +1 @@
eyJ2ZXJzaW9uIjoiMS4wLjAuMiIsImF1dGhvciI6IiIsImF1dGhlbm5hbWUiOiJWSVAxMSjlt6XkvZzljLopIiwiZGVzYyI6IiIsImRhdGEiOiJ2SSttc3BuNExrVUVuejFSU2hhK2FJK2xESlcrYkZLZXRLT1RkOWVpMTFaaXRlejBKU1psRmIvTzFlcm84WHd4UnJQcS9lVkRNL0l4cFJQM1NMWWRIQ0lZWmhYeW51ZnRCVStEbDJCL0x6V2VmNkVsT3pXRFZEeVFzUkw0c3dJSG9jUm1zVUVCMVpTbVBKdkIzVmk4V2pPY1M2d1EzcVl1TFpqb01uQmFjMnJWZHVJdkJpRjd3NzdLODg0a1B2RHdvMUxtclVPSnd4V0JqVjQ5S2RkY2c5VU9qWkdkSDlHRDRFZHMwWFp4MkNjeWwzRFozWDZZRHFUeDlnaExVVm5XUjNCV2VRNTA4RXZwTm15dXY1SENGUHd6UnpDNjcyaWIvTCsvdGVnUGxpaFRjVEhHL2duN3Z6NlRuN1VuYURDYUVYVDNwU0pVTHoyQ1E0L0hxN0hrKys3MzFGU1o3ZU9aZ01GVlpVRTBPdW5PRE04aWU3MUdEa1dvcGp2TmtJRDhaakNHdTJDdmNFU3Jpak0vZ3Y0bGMrRHpJMG1FaEZRWGphb1Bkc2c5MnBkT21yVWhlUld0a2RoNzVGb29HaFNxNFE0Rm4yMVBOcmNxUUFZWVZsZDhyT25SM2R1NGxaRFJybitlQWlkakhmK3poWElxUjZGbVFlVTdVUDNhTjRMRHM0VnlLa2VoWmtFV1gwOTg2cysxTVFGZUpJYUZpNFQrZG0xMmtYclpQL0JrbWFYSGdZOTJKKys2NzdPdnQ5SGVRakJiTnNWZkxOS3o2bmdWMFdkcjFYV3djQ2F2QmVnZkU5VnRVZ0xsRk1Rdk1OMlFkTG1DOXczclRzTUhRNWIrQWNNUGpUTXNJVlM2OGl5d3RMV01QUVlOT2RtUENtSkh0aW5zYThCUXNNOWNjTXFmZUdnMDRqZHhYcWhyaFJSYitqMngzeERwRUg4WkxXemJ0R2RoaTQxTEw2VXJVSWVtb0lUT1hFL2xXK1JRT0NnM3JtMnMxaElqdHpKWW5VLzdaRVNOZWVlSmQ4YndObWloWVU1bHphcXlwc09la3FtdnJHaFJqc1BPdkZkL3dHaHVEWVhBSEFDc3ljTkg1MENRRjNNU2N5ZSt2ckJSRGVwZkdHU3BDZlVTSUxEbmpIZTdRSFB6Z0V5MlJDZzZFODlVTTJ5Tm5RN3lSN2dvVFZaQmllVVBBK1V1cTg4UE8vbS9ac3FHKzZQSTYxTmQreUI4cmF3ODBsYjgzTjlTbmlSTTc2R3QzZk5RYkZkMzdvTjlsWEQwd1F2anJlaHg2aFRjMjgwdTlqY0VTTVJ4cnJCb213YUdXb25wRkVISXROc3JvZjlMUFd6b1VMTlhCeXNkR1BnS2w2MFJRM0JyYmFGZWdYM1Axd2J3akhXTFJCd0RwOEFvcGQ1YWNoZFhJdmk4TFA2eFkzZisvYlBLZmFBaC9aNmczbjBqMDJlMm1XVWFTVk1iK0dQSHliTSs5OTVBRnRBalNHMGhwNTB6UCtDV3JuSlVveVNOaDBXejUwZ0IzUEZpNGlNUWw1TjB6ZlNZNEhSMy9JTklhUTBFV3pJZ1RFS1piRmxFTnViQjJ6azhhSURRL1dKR2RHUFpRb0hPWHdRV0E1QzVjMkI2M0xLa1U1TjcyNmVPR1Q3bHp0SFJEVms2dDNCU0swL1JHZk4xalpzTGZaT2lBMkFJZXI4OHhLNmFsbVBtb2pYaG9EY2xBWHhmL1dmMlRVdnhhRy90NzZTQ2dzQi9rRlIvSEZIVUNDZDZubVVSQWN3NjBoeWlsMld2Q3l0QWFuLytJRTVGdTI5d3hGMjh1ZkZzQ0ZPak1BeUMreTlQa0dMTE55NCtFQ0p3NzRFOGFkSDlOVE5aYjBSZnFmNTZhdklvZ3ZXUSt6ZjJhVU0vQ1k3UEg4ZmtYWWtTUDg3cXhBZ0UrYXIrUzRvV1pvTlI0clRYMlhtMTNjdDkxMHAvbGN6b1B1UXNlbnp1SFpTOW9xVnpVb05zNUw2T1Y3ZDVBUTFNSjhhV1d0NUNqVUZZd1hNR0NUa3Y3ZmhlTktMQ2Q3RHlBSjJPdW83WHV4NjVWUkg2QUpJU1cwVkFEUlpVNTJXTnhnYkUrSkdQV2lSbTdBWG1qWHhFNk9HRE9yZ1ZwTTkzQWVCZUNVUE1PaVdicEZIQ0hGOUpRT1Z2Z3RqSmlFV05xdmhMbzhWcDlwTzQrbkQ0S3dxQWxEWU1oVk9Gd0FIRGdJVlR4QTRKbTYxakJJb3M2ZkFRVGFLcVMyTnRTeG1SVzMxdHMwSklmd3BWSWRwdzN5WGt5QzlqekpFUjFXLzRxMnZsd25WOUR2Uk9YNW9SRVk1a0FnaDhDK0dYQmhmS1BHMFdNeFU5SW9NVzJaTm9pdzdLQ2pVMVN1TFVySXlLWVg3UytJbi9IMDR3amluaUtmMEdRTjFQODZTcU5oblBxTnpPZk4xNTNSZ3RRQk92UGxIcE5uMm45cmJLLzVvTGMvbVZFVlZVdWkxMVp2cEg4cGxtRUx1QXRUL1o0SVFicDhEWnJ0dWs3T1h4bzZmYlphb1o2VHluWGVXQjVROHRDMVliYmNnRXV5YXowTExUTGIzQWRiQndKcThGNkI5NkhtdU9xRXhKTGxUZ2IwQ3cvVjFnUFNhRjBmd1hhL0FCd3crTk15d2hWTHJ5TExDMHRZdzlCZzA1Mlk4S1lrY0tmOG5hTFd4RGwwazJoTFF2VTRtVnkvSTRDYnNBN1A4aVhaaEJCdjByeFNxb0RlSXhZVTVjcmZVR3lnTFJydVE5dzY5VzZ0a2trQ3VMNTNCbGMzSEFmd0hXUWVDRlJUQUpZdzdFamtKWEtjSkFvOTJwZUZCL3pNb0tsU2I0L09xRWovOGEwMGw0SGs5ZE9hRW93K3ZkbU1lU2NjcGV2elVMZG5PR0hPOUZmbTc4MUVKN1BDL0JoTVUxbVU1ZTUycCtKZTA1ZENZY1BYZTNVY1FMMVhQQy9kWU1kbkhGaTVYYWovRUUxY2dJRGdJYXlNOUk3SnFJUzd0TW91VEtoNUZXN3M0WkJvRkdTclExam5oSXc2cktXc2VXSmVrT1pnYjcwYW9wRE1hcTEwS0RnczBEMFZ1dVl1ZGhyVnZPZlZjRXJCZWhNVHU3emVwTEtJUXA3L1NqYlNxeDh2bHJJN0dMK201bUg1T1dzQUlreWk2cnpMekNLUHBpNjloQ0FQN3lVZCtYSFUvc2VNTHp4RE9TeWFBWWxqb0VWVXUwRlhaS2VVOGt6bHpQdVozYllmWmFOQ1FuSU8wYUs5cFhiaVBRRVJoSnlLclB2THpqN0ZXSnoxWGxQTlBnWjFkQ2tmZFBRU1ZBelpDb3QzS1hBTG9acGc0QnN0ZXl6UXFpSEpMZlVnYXgrcGYxSnFpOGZhSmpoYmgrNDY1R2dyaW0rN3NoZlNLZmRvRllhNml0b084WjJsMHBoZnpERWJLREVlN2xYdzJUU2tEZkFURVR4djdHVFNFeEV1VEYvQTFuUGNTZE9xeG9vSUgxU0t2NDJOV1p4aHd6ekdpekwvMHZ0cUhCbnlINVRFUEsvY2ZhWmlVdm12SnN4OHRHWmg1NFVpNzF3NmsxWDJnWlFTSUNpQ2lGZ2RhS3lpWmQxb2ZoQ1Q0TVE3UzZqRHkzU3hNYWlSTHB0RlJMWjZWS0F4RFhDNHpRcVV0cm5UY1h4bDB0aDJWclVObHJGVDhaQkF2TFV5Zm9GWXFybTZab0k3SVRiVkNxQ1l0SldjYWduZThpcHZlbzB1RVF0ZWNkT2JOc1Z3bzliYml4akhsemlCT2RsUXpQMmdETW5mTDNSYSt6OGNtd1pLLzJYT3lURURzeUNQWGxLK2tpeXFYUjQ2WE1MTHZsYXNsZ01ORWZrTjdPbzJjdFp6Qi9LTmxVVEdXVjZXVjFHSmNUckJaTmE4RDNoblZjQm01M2pHRkFTZ293d2RTRTJYNmpYZWV4QnlmR0cwQUxVQ05NYU84K2tRQUpkY1d0WFo2RXFSN2tEVVZqMW5UMW05YTJ3S2ZZeXhIeGJLV1B6ZW5NQ2k5TjYrM0FVbTdmY205ZmtFS1NDUU5kVmZHZC9FK090UGhrNG51VmMrRkMwa3BSaW9HZ2ZoL2FSdlNZK1hYUjdsWXJ1Qk9FNlJoRHc5Z1ErMVZ2a2g0UDhNajZBRkNWbVZGaUZ5N2t5T0ZPdnFPZUQwODVRTllkQTFjdDIzZ0xBVnR1T3NUYVVOdVhDK0h0ei8wTTYwNSsvY0cyby9zaThjVUQvNS9TamEvYUpFbWZhN2UzbHhXM0xOTWVFK05aOUVXdWZkZ3h6T21FN3ZPZ3Z2aTN2YXdTcnJoU2dOZjhjQTRKN3U0cFkyZ2hKUGRVbFU2QUhkQUs3Wm53bEpXWHhoWit2Ui9rUmk0Ny9FSkw0TmlJRkVEL21xN1hGNUw1aUgxSk9yOHdXQVJVaXM3NlU0L29hU0FSTlFheWg4V1dreUg4bkRVREZrZlZYWnRnK0tIQXB4ZEVkMXNkSkZhY0hncXJMVTFQMVlRZTBTM0lPWTBtL3VObzZtODFTQWRUaFVqbmlUeTdzbFRqNGF3eCtOTzBvNHE2MFZzM3FSbElidnRXUVFvNU9ZRkk4WFdhWVNDa2lUbzlQQkFIWWhwZGVmWk1xVGxUZVJWWlJBSnhEK0pQTE85aTVZSjFVMlRiR09VZmp2YkoreUVjSFNjdHNhN0p0WmhvM3R5WmNKd0YrK21kcWxuZkJGMEdsNzREa0h6eGVEVkovWVl1d0o2WUkxTkJZa3Bjem5wTFJXZnc3ZVlOaXNNVG94VExOcFJZcmRQRlVHUzNzZHBJdkwwUWxzOEt0YitmQzdlNzhyYVBHOGRzREtLSWZqdXVvSTlPT1RLine truncated
@@ -0,0 +1,263 @@
from vnpy_ctastrategy import (
CtaTemplate,
TargetPosTemplate,
StopOrder,
TickData,
BarData,
TradeData,
OrderData,
BarGenerator,
ArrayManager,
)
import pandas as pd
import numpy as np
import math
class vip11(TargetPosTemplate):
""""""
author = "松鼠Quant"
#默认螺纹888 1H
length = 15
M=35
smoothingFactor = 0.1
TS = 50 #移动止损止盈幅度 参数范围及步长: 5-200,5
lots=1 #下单手数
fastLength = 12
slowLength = 26
MACDLength =9
current_bar = 0
Highup=0
Lowdown=0
HigherAfterEntry = float('inf')
LowerAfterEntry = -float('inf')
liQKA = 0
DliqPoint = 0
KliqPoint = 0
OBVValue=[0]
MAOBV=[0]
M2=[0]
cond1=[0]*2
cond2=[0]*2
cond3=[0]*2
kong_cond1=[0]*2
kong_cond2=[0]*2
kong_cond3=[0]*2
MACDValue=[0]*3
normalizedMACD=[1]*3
smoothedMACD=[1]*3
smoothedNormalizedMACD=[1]*3
STCValue=[1]*3
MA1=0
MA2=0
MA3=0
gobro=0
parameters = ["length",'M','smoothingFactor',"TS",'lots']
variables = ["HigherAfterEntry","LowerAfterEntry","liQKA","DliqPoint","KliqPoint"]
def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
""""""
super().__init__(cta_engine, strategy_name, vt_symbol, setting)
#df: pd.DataFrame = pd.read_csv(r"index_contract.csv")
#self.contracts_sizes = {row.vt_symbol.split('.')[0]: row.contract_size for _, row in df.iterrows()}
self.bg = BarGenerator(self.on_bar)
self.am = ArrayManager(300)
self.pos=0
def on_init(self):
"""
Callback when strategy is inited.
"""
self.write_log("策略初始化")
self.load_bar(1)
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 calculate_con(self,Price1, Price2, Length):
Matches = 0
Price2=Price2-Length
Price2list=[]
Price2list.extend([Price2 + j for j in range(1, Length)]) # 使用extend将元素添加到列表中
# 检查是否有足够的数据进行计算
if len(Price1) < Length :
return 0
else:
for i in range(1,Length-1):
# 计算Con条件
if (Price1[i] >= Price1[i-1] and Price2list[i] >= Price2list[i-1]) or \
(Price1[i] < Price1[i-1] and Price2list[i] < Price2list[i-1]):
Matches += 1
# 计算结果并返回
return 2 * Matches / Length - 1
def on_bar(self, bar: BarData):
"""
Callback of new bar data update.
"""
self.cancel_all()
am = self.am
am.update_bar(bar)
if not am.inited:
return
# 如果历史数据还没有初始化完毕,则直接返回
# 注意:am 是交易系统中的一个数据管理器,可能用于管理历史数据
# bar 是当前的K线数据,其中包含了开盘价、最高价、最低价、收盘价和成交量等信息
self.current_bar=self.current_bar+1 #Bar线计数
#print(bar.datetime,"current_bar:",self.current_bar)
# 如果当前Bar的计数器值小于self.M*2
if(self.current_bar<self.M*2):
return
#均线
self.MA1=am.ema(self.M,array=True)
self.MA2=am.ema(self.M*2,array=True)
# 如果当前Bar的计数器值小于self.MACDLength
if(self.current_bar<self.MACDLength):
return
a1 = 2 / (self.fastLength + 1)
a2 = 2 / (self.slowLength + 1)
# 计算相关系数
r2 = 0.5 * math.pow(self.calculate_con(am.close_array[-self.MACDLength:], self.current_bar, self.MACDLength), 2) + 0.5
kk = r2 * ((1 - a1) * (1 - a2)) + (1 - r2) * ((1 - a1) / (1 - a2))
# 计算MACD值
self.MACDValue.append((am.close_array[-1] - am.close_array[-2]) * (a1 - a2) + (-a2 - a1 + 2) * self.MACDValue[-1] - kk * self.MACDValue[-2])
# 如果当前Bar的计数器值小于self.fastLength
if(self.current_bar<self.fastLength):
return
lowestMACD = min(self.MACDValue[-self.fastLength:])
highestMACD = max(self.MACDValue[-self.fastLength:]) - lowestMACD
# 归一化MACD
self.normalizedMACD.append((self.MACDValue[-1] - lowestMACD) / highestMACD * 100 if highestMACD > 0 else self.normalizedMACD[-1])
# 平滑MACD
self.smoothedMACD.append(self.normalizedMACD[-1] if self.smoothedMACD[-1]==1 else self.smoothedMACD[-2] + self.smoothingFactor * (self.normalizedMACD[-1] - self.smoothedMACD[-2]))
# 计算平滑后MACD的最低值和最高值
lowestSmoothedMACD = min(self.smoothedMACD[-self.fastLength:])
highestSmoothedMACD = max(self.smoothedMACD[-self.fastLength:]) - lowestSmoothedMACD
# 归一化平滑后MACD
self.smoothedNormalizedMACD.append((self.smoothedMACD[-1] - lowestSmoothedMACD) / highestSmoothedMACD * 100 if highestSmoothedMACD > 0 else self.smoothedNormalizedMACD[-1])
# 平滑归一化后MACD,得到STC值
self.STCValue.append(self.smoothedNormalizedMACD[-1] if self.STCValue[-1]==1 else self.STCValue[-2] + self.smoothingFactor * (self.smoothedNormalizedMACD[-1] - self.STCValue[-2]))
STCvalue1=round(self.STCValue[-1]-50,0)
STCvalue2=round(self.STCValue[-2]-50,0)
STCvalue3=round(self.STCValue[-3]-50,0)
# 如果当前Bar的计数器值小于self.fastLength
if(self.current_bar<self.length):
return
Highup=max(am.high_array[-self.length:-1])
Lowdown=min(am.low_array[-self.length:-1])
#/*开平仓条件代码-----------------------------------------------------------------------------------------------------------------------------------*/
cond1=STCvalue1>STCvalue2 and STCvalue3>=STCvalue2
cond2=STCvalue1<STCvalue2 and STCvalue3<=STCvalue2
cond3=self.MA1[-1]>self.MA2[-1] and am.close_array[-1]>self.MA2[-1]
cond4=self.MA1[-1]<self.MA2[-1] and am.close_array[-1]<self.MA2[-1]
if cond1:
self.gobro=1
if cond2:
self.gobro=-1
if self.pos!=1 and self.gobro==1 and bar.high_price>=Highup and STCvalue1<0 and cond3==True:
if self.pos == 0:
self.buy(bar.close_price, self.lots)
elif self.pos < 0:
self.cover(bar.close_price, self.lots)
self.buy(bar.close_price, self.lots)
self.liQKA = 1
self.LowerAfterEntry = bar.close_price
if self.pos!=-1 and self.gobro==-1 and bar.low_price<=Lowdown and STCvalue1>0 and cond4==True :
if self.pos == 0:
self.short(bar.close_price, self.lots)
elif self.pos > 0:
self.sell(bar.close_price, self.lots)
self.short(bar.close_price, self.lots)
self.liQKA = 1
self.HigherAfterEntry = bar.close_price
#记录入场后的最高价和最低价
if self.pos>0:
#self.HigherAfterEntry = HigherAfterEntry
self.LowerAfterEntry = max(self.LowerAfterEntry, bar.low_price)
elif self.pos<0:
self.HigherAfterEntry = min(self.HigherAfterEntry, bar.high_price)
#self.LowerAfterEntry = LowerAfterEntry
if self.pos == 0:
self.liQKA = 1
else:
self.liQKA = self.liQKA - 0.1
self.liQKA = max(self.liQKA, 0.5)
if self.pos>0:
DliqPoint = self.LowerAfterEntry - ((bar.open_price)*self.TS/1000)*self.liQKA
#print(bar.datetime,"DliqPoint",DliqPoint,"low_price",bar.low_price,"self.LowerAfterEntry",self.LowerAfterEntry)
if self.pos<0:
KliqPoint = self.HigherAfterEntry + ((bar.open_price)*self.TS/1000)*self.liQKA
#print(bar.datetime,"KliqPoint",KliqPoint,"high_price",bar.high_price,"self.HigherAfterEntry",self.HigherAfterEntry)
if (self.pos>0 and bar.low_price <= DliqPoint and DliqPoint>0):
#多头出场
self.sell(bar.close_price, self.lots)
self.gobro=0
elif (self.pos<0 and bar.high_price > KliqPoint and KliqPoint>0):
#空头出场
self.cover(bar.close_price, self.lots)
self.gobro=0
self.current_bar += 1
self.put_event()
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