Skip to content

Commit ad14193

Browse files
committed
Support convertible bonds purchasing
1 parent 7160292 commit ad14193

File tree

9 files changed

+132
-1
lines changed

9 files changed

+132
-1
lines changed

README.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ ShiPanE-Python-SDK
4949
定时任务调度
5050
--------------
5151

52-
- 多账号自动新股申购(自动打新)
52+
- 多账号自动申购新股(自动打新)
53+
- 多账号自动申购转债
5354
- 多账号自动逆回购
5455
- 定时批量下单
5556
- 聚宽(JoinQuant)
@@ -142,6 +143,7 @@ Mac/Linux
142143
- examples/joinquant/simple\_strategy.py - 基本跟单用法(侵入式设计,不推荐)
143144
- examples/joinquant/advanced\_strategy.py - 高级同步、跟单用法(非侵入式设计,推荐)
144145
- examples/joinquant/new\_stocks\_purchase.py - 新股申购
146+
- examples/joinquant/convertible\_bonds\_purchase.py - 转债申购
145147
- examples/joinquant/repo.py - 逆回购
146148

147149
同步操作注意事项:
@@ -196,6 +198,7 @@ Mac/Linux
196198
- examples/ricequant/simple\_strategy.py - 基本用法
197199
- examples/ricequant/advanced\_strategy.py - 高级同步用法(非侵入式设计,推荐)
198200
- examples/ricequant/new\_stocks\_purchase.py - 新股申购
201+
- examples/ricequant/convertible\_bonds\_purchase.py - 转债申购
199202
- examples/ricequant/repo.py - 逆回购
200203

201204
二. 抓取方式

config/scheduler-template.ini

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,22 @@ schedule=0 35 11 mon-fri * * * *
6969
; clients=client1,client2
7070
clients=client1
7171

72+
; *********************************************************
73+
; 转债申购
74+
; *********************************************************
75+
[ConvertibleBonds]
76+
type=ConvertibleBonds
77+
78+
; 是否启用?
79+
enabled=false
80+
81+
; 默认设置为:星期一至星期五 11:40
82+
schedule=0 40 11 mon-fri * * * *
83+
84+
; 需要自动新股申购的交易客户端列表,以,(半角逗号)分割
85+
; clients=client1,client2
86+
clients=client1
87+
7288

7389
; *********************************************************
7490
; 逆回购
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import shipane_sdk
2+
3+
4+
# 注意:需将回测调成分钟级别
5+
# 注意:SDK内部取今日时间来获取新股数据
6+
# 注意:用于回测没有意义,需挂到“我的交易”
7+
8+
def initialize(context):
9+
# 每天的开市后10分钟进行新股申购,参数设置见:https://www.joinquant.com/api#定时运行
10+
run_daily(purchase_convertible_bonds, '9:40')
11+
12+
13+
def process_initialize(context):
14+
# 创建 StrategyManager 对象
15+
# 参数为配置文件中的 manager id
16+
g.__manager = shipane_sdk.JoinQuantStrategyManagerFactory(context).create('manager-1')
17+
18+
19+
def purchase_convertible_bonds(context):
20+
g.__manager.purchase_convertible_bonds()
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import shipane_sdk
2+
3+
4+
# 注意:需将回测调成分钟级别
5+
# 注意:SDK内部取今日时间来获取新股数据
6+
# 注意:用于回测没有意义,需挂到“模拟交易”
7+
8+
# 在这个方法中编写任何的初始化逻辑。context对象将会在你的算法策略的任何方法之间做传递。
9+
def init(context):
10+
# 每天的开市后10分钟进行新股申购。参数设置见:https://www.ricequant.com/api/python/chn#scheduler
11+
scheduler.run_daily(purchase_convertible_bonds, time_rule=market_open(minute=10))
12+
13+
14+
def before_trading(context):
15+
# 创建 RiceQuantStrategyManagerFactory 对象
16+
# 参数为 shipane_sdk_config_template.yaml 中配置的 manager id
17+
context.__manager = shipane_sdk.RiceQuantStrategyManagerFactory(context).create('manager-1')
18+
19+
20+
def purchase_convertible_bonds(context, bar_dict):
21+
context.__manager.purchase_convertible_bonds()

shipane_sdk/base_manager.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,13 @@ def repo(self):
124124
except:
125125
self._logger.exception('[%s] 逆回购失败', trader.id)
126126

127+
def purchase_convertible_bonds(self):
128+
for trader in self._traders.values():
129+
try:
130+
trader.purchase_convertible_bonds()
131+
except:
132+
self._logger.exception('[%s] 申购转债失败', trader.id)
133+
127134
def execute(self, order=None, **kwargs):
128135
if order is None and not kwargs:
129136
return
@@ -187,6 +194,12 @@ def purchase_new_stocks(self):
187194

188195
self._shipane_client.purchase_new_stocks()
189196

197+
def purchase_convertible_bonds(self):
198+
if not self._pre_check():
199+
return
200+
201+
self._shipane_client.purchase_convertible_bonds()
202+
190203
def execute(self, order=None, **kwargs):
191204
if not self._pre_check():
192205
return

shipane_sdk/client.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import pandas as pd
1010
import requests
1111
import six
12+
import tushare as ts
1213
from lxml import etree
1314
from pandas.compat import StringIO
1415
from requests import Request
@@ -142,6 +143,9 @@ def query(self, client=None, navigation=None, timeout=None):
142143
def query_new_stocks(self):
143144
return self.__query_new_stocks()
144145

146+
def query_convertible_bonds(self):
147+
return self.__query_convertible_bonds()
148+
145149
def purchase_new_stocks(self, client=None, timeout=None):
146150
today = datetime.datetime.strftime(datetime.datetime.today(), '%Y-%m-%d')
147151
df = self.query_new_stocks()
@@ -160,6 +164,24 @@ def purchase_new_stocks(self, client=None, timeout=None):
160164
self._logger.error(
161165
'客户端[{}]申购新股[{}({})]失败\n{}'.format((client or self._client), row['name'], row['code'], e))
162166

167+
def purchase_convertible_bonds(self, client=None, timeout=None):
168+
today = datetime.datetime.strftime(datetime.datetime.today(), '%Y-%m-%d')
169+
df = self.query_convertible_bonds()
170+
df = df[(df.ipo_date == today)]
171+
self._logger.info('今日有[{}]支可申购转债'.format(len(df)))
172+
for index, row in df.iterrows():
173+
try:
174+
order = {
175+
'symbol': row['xcode'],
176+
'price': 100,
177+
'amountProportion': 'ALL'
178+
}
179+
self._logger.info('申购转债:{}'.format(order))
180+
self.buy(client, timeout, **order)
181+
except Exception as e:
182+
self._logger.error(
183+
'客户端[{}]申购转债[{}({})]失败\n{}'.format((client or self._client), row['name'], row['code'], e))
184+
163185
def create_adjustment(self, client=None, request_json=None, timeout=None):
164186
request = Request('POST', self.__create_url(client, 'adjustments'), json=request_json)
165187
request.headers['Content-Type'] = MediaType.JOIN_QUANT.value
@@ -200,6 +222,10 @@ def __query_new_stocks(self):
200222
df['xcode'] = df['xcode'].map(lambda x: str(x).zfill(6))
201223
return df
202224

225+
def __query_convertible_bonds(self):
226+
df = ts.new_cbonds()
227+
return df
228+
203229
def __create_order_url(self, client=None, order_id=None, **params):
204230
return self.__create_url(client, 'orders', order_id, **params)
205231

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from shipane_sdk.jobs.basic_job import BasicJob
4+
5+
6+
class ConvertibleBondsPurchaseJob(BasicJob):
7+
def __init__(self, client, client_aliases=None, name=None, **kwargs):
8+
super(ConvertibleBondsPurchaseJob, self).__init__(name, kwargs.get('schedule', None), kwargs.get('enabled', False))
9+
10+
self._client = client
11+
self._client_aliases = client_aliases
12+
13+
def __call__(self):
14+
for client_alias in self._client_aliases:
15+
try:
16+
client = self._client_aliases[client_alias]
17+
self._client.purchase_convertible_bonds(client)
18+
except:
19+
self._logger.exception('客户端[%s]申购转债失败', client_alias)

shipane_sdk/scheduler.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from shipane_sdk.ap import APCronParser
1919
from shipane_sdk.guorn.client import GuornClient
2020
from shipane_sdk.jobs.batch import BatchJob
21+
from shipane_sdk.jobs.convertible_bonds_purchase import ConvertibleBondsPurchaseJob
2122
from shipane_sdk.jobs.new_stock_purchase import NewStockPurchaseJob
2223
from shipane_sdk.jobs.online_quant_following import OnlineQuantFollowingJob
2324
from shipane_sdk.jobs.online_quant_sync import OnlineQuantSyncJob
@@ -69,6 +70,8 @@ def __create_job(self, section):
6970
job = None
7071
if job_type == 'NewStocks':
7172
job = self.__create_new_stock_purchase_job(section)
73+
elif job_type == 'ConvertibleBonds':
74+
job = self.__create_convertible_bonds_job(section)
7275
elif job_type == 'Repo':
7376
job = self.__create_repo_job(section)
7477
elif job_type == 'Batch':
@@ -90,6 +93,11 @@ def __create_new_stock_purchase_job(self, section):
9093
client_aliases = self.__filter_client_aliases(section)
9194
return NewStockPurchaseJob(self._client, client_aliases, '{}-Job'.format(section), **options)
9295

96+
def __create_convertible_bonds_job(self, section):
97+
options = self.__build_options(section)
98+
client_aliases = self.__filter_client_aliases(section)
99+
return ConvertibleBondsPurchaseJob(self._client, client_aliases, '{}-Job'.format(section), **options)
100+
93101
def __create_repo_job(self, section):
94102
options = self.__build_options(section)
95103
client_aliases = self.__filter_client_aliases(section)

tests/shipane_sdk/test_client.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,8 @@ def test_query(self):
119119
def test_query_new_stocks(self):
120120
df = self.client.query_new_stocks()
121121
self.assertTrue((df.columns == ['code', 'xcode', 'name', 'ipo_date', 'price']).all())
122+
123+
def test_query_convertible_bonds(self):
124+
df = self.client.query_convertible_bonds()
125+
assert_that(df, has_column('ipo_date'))
126+
assert_that(df, has_column('xcode'))

0 commit comments

Comments
 (0)