
等级: 新手上路
- 注册:
- 2021-7-30
- 曾用名:
|

楼主 |
发表于 2025-7-23 11:50
|
显示全部楼层
# 本Python代码主要用于策略交易
# 可以自己import我们平台支持的第三方python模块,比如pandas、numpy等。
from PythonApi import *
import datetime
import re # 导入正则表达式模块
import numpy as np
from datetime import datetime # ← 直接导入类
# 在这个方法中编写任何的初始化逻辑。context对象将会在算法策略运行时使用
def init(context):
# 在context中保存全局变量
block = get_blocks('自选股', 1) # ['DQLH09','DQP09']
context.universe = block # 将交易的合约设置为连续合约
context.account_id = None # 初始时设置为None
# 设置定时器,每2秒执行一次GridTrade函数
settimer(GridTrade,2000) # 2秒执行一次
# 初始化账户信息
update_account_info(context)
# GridTrade函数(每2秒执行一次)
#退出程序后杀死计时器
def exit(context):
killtimer(GridTrade)
def GridTrade(context):
write_logging("=== GridTrade 触发 ===")
buy_open_long2(context)
portfolio_query_module(context)
def buy_open_long2(context):
codes = context.universe
write_logging(f"当前股票池: {codes}")
if not codes:
write_logging("股票池为空,跳过")
return
for code in codes:
stock_code_num = re.sub(r'\D', '', code)
longtrades = stock_code_num + "_longstoday"
write_logging(f"检查信号: {longtrades}")
signal = getextdata(longtrades)
write_logging(f"信号值: {signal}")
if signal == 1:
write_logging(f"满足开仓条件,准备买入: {code}")
buy_open_module(context, code, len(codes))
setextdata(longtrades, 2)
write_logging("已设置信号为 2")
else:
write_logging(f"不满足开仓条件,跳过: {code}")
def buy_open_module(context, code, blocks):
write_logging("=== buy_open_module start ===")
write_logging(f"入参 code={code} blocks={blocks}")
# 1) 生成信号 key
stock_code_num = re.sub(r'\D', '', code)
longtrades_key = stock_code_num + "_longstoday"
write_logging(f"longtrades_key = {longtrades_key}")
# 2) 读取资金数据
available_funds = getextdata('available_funds')
dynastic_rights = getextdata('dynastic_rights')
write_logging(f"available_funds = {available_funds}")
write_logging(f"dynastic_rights = {dynastic_rights}")
# 3) 资金比例判断
if blocks == 0:
write_logging("blocks == 0,直接退出")
return
if dynastic_rights is None or dynastic_rights == 0:
write_logging("dynastic_rights 为 None 或 0,无法计算比例,退出")
return
if available_funds is None:
write_logging("available_funds 为 None,退出")
return
ratio = available_funds / dynastic_rights
write_logging(f"资金比例 = {ratio:.4f}")
if ratio <= 0.2:
write_logging("资金比例 <= 0.2,不满足开仓条件")
return
# 4) 计算每只股票可分配金额
value = available_funds / max(3, blocks)
write_logging(f"每只股票可分配金额 value = {value}")
# 5) 获取最新价
current_price = np.round(get_dynainf(code, 7), 2)
write_logging(f"最新价 current_price = {current_price}")
if current_price is None or current_price <= 0:
write_logging(f"未获取到 {code} 的有效最新价,退出")
return
# 6) 获取涨停价(字段 54)
limit_up = np.round(get_dynainf(code, 54), 2)
write_logging(f"涨停价 limit_up = {limit_up}")
if limit_up is None or limit_up <= 0:
write_logging("涨停价无效,退出")
return
# 7) 检查最小买入金额
min_buy = 100 * current_price
write_logging(f"最小买入金额(100 股) = {min_buy}")
if value < min_buy:
write_logging("可分配金额不足以买入 100 股,退出")
return
# 8) 价格条件判断
write_logging(f"价格判断: current_price {current_price} <= limit_up {limit_up}")
if current_price <= limit_up:
write_logging("满足开仓条件,准备下单")
# 检查你的代码中所有 buy_open 调用,统一改为:
# 按金额买入(volume=0)
#市价委托方式,买入平安银行1000股
buy_open(code, "Market", 0 , value,serial_id = 1)
write_logging(f"下单返回 order_id = {order_id}")
setextdata(longtrades_key, 2)
write_logging(f"已设置 {longtrades_key} = 2")
else:
write_logging("最新价高于涨停价,不开仓")
write_logging("=== buy_open_module end ===")
# 打印账户中的股票持仓信息
## 示例用法
def handle_bar(context):
# 更新账户信息
update_account_info(context)
# 这里可以添加根据持仓和账户信息进行交易逻辑的代码
#def buy_open_long(context):
# codes = context.universe
# # 开仓前持仓全集变量
#
# if len(codes) == 0:
# return
#
# for code in codes:
# # 提取股票代码中的数字部分
# stock_code_num = re.sub(r'\D', '', code)
# longtrades = stock_code_num + "_longstoday"
#
## if not istradertime(code):
## continue
# if getextdata('longtrades')==1:
# # 示例开仓
# buy_open_module(context, code, len(codes) )
# setextdata('longtrades',2)
def buy_open_long(context):
codes = context.universe
print("当前股票池 codes:", codes)
if len(codes) == 0:
print("股票池为空,跳过开仓逻辑")
return
for code in codes:
print(f"处理股票: {code}")
# 提取股票代码中的数字部分
stock_code_num = re.sub(r'\D', '', code)
longtrades = stock_code_num + "_longstoday"
print(f"生成的 longtrades 键名: {longtrades}")
# 获取 longtrades 的扩展数据
ext_value = getextdata(longtrades)
print(f"getextdata('{longtrades}') 的值为: {ext_value}")
if ext_value == 1:
print(f"条件满足,准备开仓: {code}")
buy_open_module(context, code, len(codes))
setextdata(longtrades, 2)
print(f"已设置 {longtrades} 为 2")
else:
print(f"条件不满足,跳过开仓: {code},值为 {ext_value}")
# BUY开仓模块
#def buy_open_module(context, code ,blocks):
# # 保存全局变量longtrades,表示开仓前的持仓情况
# # 开仓前持仓全集变量
# # 提取股票代码中的数字部分
# stock_code_num = re.sub(r'\D', '', code)
# longtrades = stock_code_num + "_longstoday"
# #setextdata('longtrades', volume)
## dynastic_rights = getextdata('dynastic_rights')
## available_funds = getextdata('available_funds')
# if blocks != 0 and getextdata('available_funds')/ getextdata('dynastic_rights') > 0.2:
# # Calculate the value per security (though we'll only use it for the first three)
# value = getextdata('available_funds')/ max(3, blocks)
# # 获取最新价格
# #获取rb00当前最新价
# #get_dynainf('SQRB00', 7)
# current_price = np.round(get_dynainf(code, 7),2)
# if current_price is None:
# write_logging(f"未获取到 {code} 的最新价格。")
# # Calculate the ratio for all qualified stocks
# # Check if we can buy at least 100 shares
# if value / get_dynainf(code, 54) > 100:
# # Determine the order value based on the ratio
# if current_price <= np.round(get_dynainf(code, 54),2):#价格54是涨停
# # 执行开仓操作
# # 使用账号'12345'以市价方式买入价值20000元的螺纹钢
# buy_open(code, "Market", amount=value,serial_id = 1)
# #order_id = buy_open(code, 'Limit', current_price, value,serial_id = 1)# 控制每次下单金额为value
# setextdata('longtrades',2)
## if current_price <= np.round(min(get_dynainf(code, 28)*1.02,get_dynainf(code, 54)),2):#49是买五价,54是涨停,51卖五价
## # 执行开仓操作
## # 使用账号'12345'以市价方式买入价值20000元的螺纹钢
## #buy_open(code, "Market", amount=value,serial_id = 1)
## #buy_open(code, 'Limit', np.round(min(get_dynainf(code, 28)*1.02,get_dynainf(code, 54)),2), value,serial_id = 2)# 控制每次下单金额为value
## setextdata('longtrades',2)
# SELL平仓模块
def sellclose_module(context, code, price, volume):
try:
# 获取全局变量stopline,表示持仓信息平仓变量
# ---------- 当前时间 ----------
now = datetime.now()
current_time = now.time()
#write_logging(f"当前时间: {current_time}")
#current_time = datetime.datetime.now().time()
# 提取小时和分钟
current_hour = current_time.hour
current_minute = current_time.minute
#write_logging(f"当前时间: {current_hour}:{current_minute}")
# 提取股票代码中的数字部分
stock_code_num = re.sub(r'\D', '', code)
stopline_key = f"{stock_code_num}_stopline"
# 如已标记平仓则直接跳过
if int(getextdata(stopline_key) or 0) == 1:
write_logging(f"{code} 已平仓,跳过")
return None
# 获取最新价格
#get_dynainf('SQRB00', 7)
current_price = np.round(get_dynainf(code, 7),2)
Lower_Limitprice=np.round(get_dynainf(code, 55),2)#55,跌停,请用英文
if current_price is None:
write_logging(f"未获取到 {code} 的最新价格。")
return
# 读取成本价格
cost_price = getextdata(f'{stock_code_num}_cost')
if cost_price is None:
write_logging(f"未获取到 {code} 的成本价格。")
return
# 获取五日均线价格
close_data = history_bars(code, 5, '1d', 'CLOSE')
if close_data is not None :
ma5 = np.round(np.mean(close_data),2)
#write_logging(f"五日均线价格:{ma5}: {code}:{price}:{volume}:{current_price}")
# 上午10点:亏损5%时平仓,get_dynainf函数55跌停
if current_time.hour == 10 and current_time.minute == 0:
if (cost_price - current_price) / cost_price >= 0.05:
sell_close(code, 'Limit', Lower_Limitprice, volume,serial_id = 2)
setextdata(stopline_key, 1) # ← 关键:标记已平仓
write_logging(f"亏损5%平仓: {code}, 成本价格: {cost_price}, 当前价格: {current_price}")
return order_id
# 上午11点:当前最新价格低于昨日收盘价时平仓
elif current_time.hour == 11 and current_time.minute == 0:
# 获取昨日收盘价
yesterday_close = get_dynainf(code, 3)
if current_price < yesterday_close:
order_id = sell_close(code, 'Limit', Lower_Limitprice, volume,serial_id = 3)
setextdata(stopline_key, 1) # ← 关键:标记已平仓
write_logging(f"低于昨日收盘价平仓: {code}, 昨日收盘价: {yesterday_close}, 当前价格: {current_price}")
return order_id
# 下午2点50分:当前最新价格低于五日均线价格时平仓
elif current_time.hour == 14 and current_time.minute == 26:
stock_code_num = re.sub(r'\D', '', code)
stopline_key = stock_code_num + "_stopline"
stopline = int(getextdata(stopline_key) or 0)
if stopline == 1:
write_logging(f"{code} {stopline_key}=1,已平仓,跳过")
return None
else:
#order_id = None
if current_price < ma5:
order_id = sell_close(code, 'Limit', Lower_Limitprice, volume,serial_id = 4)
setextdata(stopline_key, 1) # ← 关键:标记已平仓
write_logging(f"低于五日均线平仓: {code}, 五日均线: {ma5}, 当前价格: {current_price}")
return order_id
except Exception as e:
write_logging(f"执行平仓模块时发生错误: {e}")
return None
# 持仓查询模块
def portfolio_query_module(context):
try:
# 确保account_id已初始化
if not hasattr(context, 'account_id') or context.account_id is None:
write_logging("账户ID未初始化,无法查询持仓信息。")
return
# 获取账户中的所有持仓品种
account_stocks = get_portfolio_book(2, context.account_id)
if account_stocks:
#write_logging("账户中的股票持仓:")
for stock in account_stocks:
# 提取股票代码中的数字部分
stock_code_num = re.sub(r'\D', '', stock)
#write_logging(f"股票代码: {stock}, 数字部分: {stock_code_num}")
# 查询该股票的持仓详情
try:
portfolio = get_portfolio(stock, 2, context.account_id)
if portfolio:
total_position = portfolio.buy_quantity + portfolio.sell_quantity
available_position = portfolio.buy_today_quantity + portfolio.sell_today_quantity
cost_price = portfolio.buy_avg_holding_price
#write_logging(f" 总持仓: {total_position}, 今日可用持仓: {available_position}, 持仓成本: {cost_price}")
# 将持仓信息保存到全局变量,格式为 "s_数字部分_信息类型"
setextdata(f'{stock_code_num}_total', total_position)
setextdata(f'{stock_code_num}_avail', available_position)
setextdata(f'{stock_code_num}_cost', cost_price)
# 示例平仓
sellclose_module(context, stock, cost_price, available_position)
else:
write_logging(f" 未获取到 {stock} 的持仓详情。")
except Exception as e:
write_logging(f"查询 {stock} 的持仓详情时发生错误: {e}")
else:
write_logging("账户中没有股票持仓。")
except Exception as e:
write_logging(f"获取账户持仓品种时发生错误: {e}")
# 更新账户信息函数
# 假设平台定义如下(需替换为你的实际参数)
def update_account_info(context):
try:
# 获取当前登录账户列表
accounts = get_account_book()
if not accounts:
write_logging("未检测到任何登录账户")
return
account_no = accounts[0] # 默认取第一个登录账户
write_logging(f"使用账户: {account_no}")
# 判断账户是否有效
if not isaccount(account_no):
write_logging("账户未登录或无效")
return
# 获取账户信息
cash_balance = get_account(3, account_no)
floating_profit = get_account(4, account_no)
dynastic_rights = get_account(6, account_no)
available_funds = get_account(19, account_no)
# 保存到扩展数据
setextdata('cash_balance', cash_balance or 0)
setextdata('floating_profit', floating_profit or 0)
setextdata('dynastic_rights', dynastic_rights or 0)
setextdata('available_funds', available_funds or 0)
write_logging(f"账户信息更新成功 - 现金余额: {cash_balance}, 可用资金: {available_funds}")
except Exception as e:
write_logging(f"更新账户信息失败: {e}")
# 测试代码
|
|