PS:本人2021-09-24在聚宽平台注册账号开始学习,特此开贴记录学习过程,欢迎大家一起交流(本人目前只关注场外基金策略的学习研究,暂时不涉及股票)
1、如何运行示例代码?
登录平台官网后,进入“我的策略”页:https://www.joinquant.com/view/user/floor?type=mainFloor
可以看到“我的策略”列表里提供了5个示例策略,点击“双均线策略”进入详情页,然后就可以直接运行或者编辑了
2、申请试用账户本地环境调试
官方说明如下:https://www.joinquant.com/help/api/help#JQData:JQData开通、登陆、流量查询及购买方法
申请页链接:https://www.joinquant.com/default/index/sdk#jq-sdk-apply
基本填好资料几分钟后就申请好了,试用账户说明如下:
账户类型:试用账户(免费)
账户有效期:六个月
可用数据:全部基础数据
可查询数据时间范围:2005年至今
每天调用数据限制:100万条/天
单个账号可同时开启连接数:1个
3、PyCharm本地调试
搜索下载安装包:jqdatasdk,安装成功后运行如下demo可以测试是否连接成功
```
"""
聚宽API使用demo
"""
from jqdatasdk import *
# 主函数
def main():
# 账户认证,注册手机号、网站登录密码
auth('注册手机号', '网站登录密码')
# 查询当日剩余可调用数据条数
count = get_query_count()
print(count)
# 程序入口
if __name__ == '__main__':
main()
```
控制台出现如下提示说明连接成功

4、本地获取招商中证白酒基金净值
```
"""
聚宽API使用demo
"""
from jqdatasdk import *
# 主函数
def main():
# 账户认证,注册手机号、网站登录密码
auth('注册手机号', '网站登录密码')
# 查询当日剩余可调用数据条数
count = get_query_count()
print('每日总量:' + str(count['total']))
print('调用余量:' + str(count['spare']))
# 当天调用量用完则不执行查询
if count['spare'] < 1:
print('今日免费调用量已用完!')
return
# 招商中证白酒基金代码
fund_code = '161725'
fund_info = query(finance.FUND_MAIN_INFO).filter(finance.FUND_MAIN_INFO.main_code == fund_code)
df = finance.run_query(fund_info)
print(df[['main_code', 'name', 'advisor', 'operate_mode', 'start_date']])
fund_value = query(finance.FUND_NET_VALUE).filter(finance.FUND_NET_VALUE.code == fund_code).order_by(
finance.FUND_NET_VALUE.day.desc()).limit(10)
df = finance.run_query(fund_value)
print(df[['code', 'day', 'net_value', 'sum_value']])
# 程序入口
if __name__ == '__main__':
main()
```
执行结果

PS:平台接口返回数据大多是以dataframe对象的形式,关于df对象的处理可以参考下面的官方教程:
https://www.joinquant.com/view/community/detail/fcc74204986b03f90d1fc4e769c2b2b8
5、在官网编辑运行场外基金策略
官方教程参考:https://www.joinquant.com/help/api/help#name:api
(1)在我的策略列表页选择场外基金模板新建策略
https://www.joinquant.com/algorithm/index/list

(2)在场外基金模板的示例代码基础上修改编辑

API使用说明:
```
# Context属性:
# subportfolios: 当前单个操作仓位的资金、标的信息,是一个SubPortfolio 的数组
# portfolio: 账户信息,即subportfolios 的汇总信息, Portfolio对象,单个操作仓位时,portfolio 指向 subportfolios[0]
# current_dt: 当前单位时间的开始时间, [datetime.datetime]对象
# previous_date: 前一个交易日, [datetime.date]对象, 注意, 这是一个日期, 是 date, 而不是 datetime
# ----------- Portfolio 常用属性 —————————————
# inout_cash: 累计出入金, 比如初始资金 1000, 后来转移出去 100, 则这个值是 1000 - 100
# available_cash: 可用资金, 可用来购买证券的资金
# transferable_cash: 可取资金, 即可以提现的资金, 不包括今日卖出证券所得资金
# long_positions: 多单的仓位, 一个 dict, key 是证券代码, value 是 [Position]对象
# total_value: 总的权益, 包括现金, 保证金(期货)或者仓位(股票)的总价值, 可用来计算收益
# returns: 总权益的累计收益;(当前总资产 + 今日出入金 - 昨日总资产) / 昨日总资产;
# starting_cash: 初始资金, 现在等于 inout_cash
# positions_value: 持仓价值
# ----------- SubPortfolio 常用属性 —————————————
# inout_cash: 累计出入金, 比如初始资金 1000, 后来转移出去 100, 则这个值是 1000 - 100
# available_cash: 可用资金, 可用来购买证券的资金
# transferable_cash: 可取资金, 即可以提现的资金, 不包括今日卖出证券所得资金
# long_positions: 多单的仓位, 一个 dict, key 是标的代码, value 是 [Position]对象
# total_value: 总资产
# total_liability: 总负债
# net_value: 净资产, 等于总资产减去总负债
# positions_value: 持仓价值
# ----------- Position 常用属性 -----------
# security: 标的代码,场外基金编码
# total_amount: 总仓位,持仓基金份额
# closeable_amount: 可卖出的仓位 / 场外基金持有份额
# price: 最新行情价格,
# value: 标的价值,price * total_amount * multiplier, 股票、基金的multiplier为1
```
(3)简单策略demo代码,帮大家省点拷贝积分
```
# 导入函数库
from jqdata import *
import datetime
# 初始化函数,设定基准等等
def initialize(context):
# 全局变量,记录交易天数
g.day = 0
# 全局变量,保存基金编码
g.code = '005918.OF'
fund_info = get_fund_info(g.code)
# 全局变量,保存基金名称
g.name = fund_info['fund_name']
log.info("选中基金名称:",g.name)
# 设置仓位,目前只设置场外基金单个操作仓位,subportfolios[0]与portfolio指向同一个对象
set_subportfolios([SubPortfolioConfig(context.portfolio.starting_cash, 'open_fund')])
# 用基金的单位净值进行撮合成交
set_option('use_real_price', True)
# 设置基金赎回到账日为 T+3
set_redeem_latency(3, 'open_fund')
# 设置基金交易费率
set_order_cost(OrderCost(),type='open_fund', ref='005918.OF')
# 设定比较基准,国证A指 399317.XSHE
set_benchmark('399317.XSHE')
log.info("账户初始资金:",context.portfolio.starting_cash)
## 运行函数(reference_security为运行时间参考标的,传什么无所谓)
# 每天开盘时运行
run_daily(market_open, time='open', reference_security='000300.XSHG')
# 每天收盘后运行
run_daily(after_market_close, time='after_close', reference_security='000300.XSHG')
def market_open(context):
log.info('##############################################################')
s = g.code
#得到"年-月-日"格式的当前交易日期
date = context.current_dt.strftime("%Y-%m-%d")
log.info('当前交易日期:',date)
start_date_str = (context.previous_date + datetime.timedelta(days=-30)).strftime("%Y-%m-%d")
end_date_str = context.previous_date
log.info('start_date:',start_date_str)
log.info('end_date:',end_date_str)
# 获取最近30天基金净值
df = get_extras('unit_net_value', g.code, start_date=start_date_str, end_date=end_date_str, df=True, count=None)
# 最近30天净值最小值
min_value = df[g.code].min()
log.info('min_value',min_value)
# 买入条件:基金最新净值 - 前30天最小净值 < 0.1
if context.portfolio.long_positions[g.code].price - min_value < 0.1:
log.info(purchase(g.code, 10000))
else:
log.info('今日不买入')
# 可卖份额
amount = context.portfolio.long_positions[g.code].closeable_amount
# 卖出条件:基金收益率超过100%,清仓;超过50%,卖出一半
if context.portfolio.returns > 1.0:
log.info(redeem(g.code, amount))
elif context.portfolio.returns > 0.5:
log.info(redeem(g.code, amount/2))
else:
log.info('今日不卖出')
## 收盘后运行函数
def after_market_close(context):
# 查看融资融券账户相关相关信息(更多请见API-对象-SubPortfolio)
p = context.portfolio
log.info('- - - - - - - - - - - 当日收盘统计 - - - - - - - - - - - - - -')
log.info('账户总体价值:',p.total_value)
log.info('账户总收益率:',p.returns)
log.info('账户可用资金:',p.available_cash)
log.info('基金持仓份额:',p.long_positions[g.code].closeable_amount)
log.info('基金持仓价值:',p.long_positions[g.code].value)
log.info('基金最新价格:',p.long_positions[g.code].price)
```
PS:简单策略demo回测效果图在最下面
(4)使用实盘模拟交易验证策略
进入模拟列表页
https://www.joinquant.com/algorithm/trade/list?process=1
新建模拟策略

6、大神基金策略学习
https://www.joinquant.com/view/community/detail/cd8a9a87ea3a3cda16a9610b5f1900ec