# 策略中必须有init方法
|
import json
|
import threading
|
import time
|
|
import gm.api as gmapi
|
import xlwt
|
|
import setting
|
from utils import tool
|
|
|
def init(context):
|
global gpCodeManager
|
gpCodeManager = GPCodeManager()
|
# 订阅股票代码
|
subscript()
|
# t1 = threading.Thread(target=lambda: __run_schedule())
|
# # 后台运行
|
# t1.setDaemon(True)
|
# t1.start()
|
|
|
#
|
# def __run_schedule():
|
# while True:
|
# st = __pipe.recv()
|
# if st:
|
# print("读取到内容", st)
|
# if st == "resub":
|
# subscript()
|
|
|
def subscript():
|
# 清除收盘价
|
GPCodeManager.pre_prices.clear()
|
# __get_latest_price()
|
|
# t1 = threading.Thread(target=lambda: __get_latest_price())
|
# # 后台运行
|
# t1.setDaemon(True)
|
# t1.start()
|
|
# # 读取订阅代码
|
codes = gpCodeManager.get_codes()
|
gpcode_list = GPCodeManager.get_gp_list_with_prefix(codes)
|
if gpcode_list:
|
codes_str = ",".join(gpcode_list)
|
print("订阅:", codes_str)
|
gmapi.subscribe(symbols=codes_str, frequency='tick', count=2, wait_group=False, wait_group_timeout='10s',
|
unsubscribe_previous=True)
|
|
|
# 获取最新的现价
|
def __get_latest_price():
|
_last_create_time_dict = {}
|
# strategy_id, token = setting.get_juejin_params()
|
# gmapi.set_token(token)
|
gpCodeManager = GPCodeManager()
|
while True:
|
try:
|
if tool.is_trade_time():
|
codes = gpCodeManager.get_codes()
|
gpcode_list = GPCodeManager.get_gp_list_with_prefix(codes)
|
if gpcode_list:
|
codes_str = ",".join(gpcode_list)
|
datas = gmapi.current(symbols=codes_str, fields="symbol,price,cum_amount,cum_volume,created_at")
|
for data in datas:
|
if _last_create_time_dict.get(data['symbol']) == data['created_at']:
|
print("重复数据")
|
continue
|
_last_create_time_dict[data['symbol']] = data['created_at']
|
on_tick(None, data)
|
except:
|
pass
|
time.sleep(15)
|
|
|
def parse_tick(tick):
|
symbol = tick['symbol']
|
price = tick['price']
|
# 保存最新价
|
symbol = symbol.split(".")[1]
|
pre_price = GPCodeManager().get_pre_prices(symbol)
|
average_price = round(tick["cum_amount"] / tick["cum_volume"], 2) if tick["cum_volume"] > 0 else pre_price
|
rate = round((price - pre_price) / pre_price, 4)
|
average_rate = round((average_price - pre_price) / pre_price, 4)
|
data = {"code": symbol, "rate": rate, "created_at": tick["created_at"], "price": price,
|
"average_price": average_price, "average_rate": average_rate}
|
return data
|
|
|
def on_tick(context, tick):
|
print(tick)
|
if int(tick['created_at'].strftime("%H:%M:%S").replace(":", "")) < int("092500"):
|
return
|
data = parse_tick(tick)
|
data = {"type": 0, "data": data}
|
__pipe.send(data)
|
|
|
def run(pipe):
|
global __pipe, token
|
__pipe = pipe
|
strategy_id, token = setting.get_juejin_params()
|
gmapi.set_token(token)
|
gmapi.run(strategy_id=strategy_id,
|
filename='juejin_core.py',
|
mode=gmapi.MODE_LIVE,
|
token=token)
|
# 测试订阅
|
# gmapi.run(strategy_id=strategy_id,
|
# filename='juejin_core.py',
|
# mode=gmapi.MODE_BACKTEST,
|
# backtest_start_time="2023-10-09 09:25:00",
|
# backtest_end_time="2023-10-09 09:40:00",
|
# backtest_initial_cash=1000000,
|
# backtest_transaction_ratio=1, backtest_commission_ratio=0,
|
# backtest_slippage_ratio=0, backtest_adjust=gmapi.ADJUST_NONE, backtest_check_cache=0,
|
# serv_addr='', backtest_match_mode=0,
|
# token=token)
|
subscript()
|
|
|
class GPCodeManager:
|
pre_prices = {}
|
|
def __init__(self):
|
strategy_id, token = setting.get_juejin_params()
|
self.strategy_id = strategy_id
|
self.token = token
|
|
@classmethod
|
def get_gp_list_with_prefix(cls, data):
|
list = []
|
for d in data:
|
if d[0:2] == '00':
|
list.append("SZSE.{}".format(d))
|
elif d[0:2] == '60':
|
list.append("SHSE.{}".format(d))
|
return list
|
|
def __get_pre_prices(self, code):
|
symbols = self.get_gp_list_with_prefix([code])
|
gmapi.set_token(self.token)
|
datas = gmapi.get_instruments(symbols=",".join(symbols))
|
for data in datas:
|
symbol = data['symbol']
|
symbol = symbol.split(".")[1]
|
price = round(data['pre_close'], 2)
|
if symbol == code:
|
return price
|
return None
|
|
def __get_codes_names(self, codes):
|
codes_names = []
|
if not codes:
|
return codes_names
|
symbols = self.get_gp_list_with_prefix(codes)
|
gmapi.set_token(self.token)
|
datas = gmapi.get_instruments(symbols=",".join(symbols))
|
for data in datas:
|
symbol = data['symbol']
|
symbol = symbol.split(".")[1]
|
code_name = data['sec_name']
|
price = round(data['pre_close'], 2)
|
codes_names.append((symbol, code_name, price))
|
# 根据codes排序
|
codes_index = {}
|
for i in range(0, len(codes)):
|
codes_index[codes[i]] = i
|
codes_names.sort(key=lambda x: codes_index.get(x[0]))
|
|
return codes_names
|
|
# 获取昨日收盘价
|
def get_pre_prices(self, code):
|
if code in self.pre_prices:
|
return self.pre_prices[code]
|
# 获取昨日收盘价
|
price = self.__get_pre_prices(code)
|
if price:
|
self.pre_prices[code] = price
|
return price
|
|
def get_history_tick_n(self, code, count, frequency="1d", end_time=None):
|
symbols = self.get_gp_list_with_prefix([code])
|
gmapi.set_token(self.token)
|
results = gmapi.history_n(symbol=symbols[0], frequency=frequency, count=count, end_time=end_time)
|
last_data = None
|
for result in results:
|
try:
|
rate = None
|
if last_data is None:
|
rate = round(result["last_amount"] / result["last_volume"], 2)
|
else:
|
rate = round((result["last_amount"] - last_data["last_amount"]) / (
|
result["last_volume"] - last_data["last_volume"]), 2)
|
except:
|
pass
|
last_data = result
|
return results
|
|
def get_lowest_price_rate(self, code, count):
|
datas = self.get_history_tick_n(code, count)
|
low_price = datas[0]["close"]
|
for data in datas:
|
if low_price > data["close"]:
|
low_price = data["close"]
|
return (datas[-1]["close"] - low_price) / low_price
|
|
def get_history_tick(self, code, start_time_str, end_time_str):
|
symbols = self.get_gp_list_with_prefix([code])
|
gmapi.set_token(self.token)
|
results = gmapi.history(symbol=symbols[0], frequency="tick", start_time=start_time_str, end_time=end_time_str)
|
last_data = None
|
for result in results:
|
try:
|
rate = None
|
if last_data is None:
|
rate = round(result["last_amount"] / result["last_volume"], 2)
|
else:
|
rate = round((result["last_amount"] - last_data["last_amount"]) / (
|
result["last_volume"] - last_data["last_volume"]), 2)
|
except:
|
pass
|
# print(result["created_at"], rate, result["price"],result["open"],result["high"],result["low"])
|
last_data = result
|
return results
|
|
def get_min_and_max_price(self, codes):
|
symbols = self.get_gp_list_with_prefix(codes)
|
gmapi.set_token(self.token)
|
results = gmapi.current(symbols)
|
fresults = []
|
for result in results:
|
fresults.append((result["symbol"].split(".")[1], result["low"], result["high"]))
|
return fresults
|
|
def get_current_price(self, code):
|
symbols = self.get_gp_list_with_prefix([code])
|
gmapi.set_token(self.token)
|
results = gmapi.current(symbols)
|
return results
|
|
# 获取代码
|
def get_codes(self):
|
codes = []
|
with open("res/codes.txt", "r") as f:
|
while True:
|
line = f.readline()
|
if not line:
|
break
|
codes.append(line.strip())
|
return codes
|
|
def get_codes_with_names(self):
|
codes = self.get_codes()
|
return self.__get_codes_names(codes)
|
|
# 设置代码
|
def set_codes(self, codes):
|
with open("res/codes.txt", "w") as f:
|
for code in codes:
|
f.write(code)
|
f.write("\n")
|
|
|
class JueJinApi:
|
__previous_trading_date_cache = {}
|
|
# 获取掘金参数
|
@classmethod
|
def getJueJinAccountInfo(cls):
|
strategy_id, token = setting.get_juejin_params()
|
return "", strategy_id, token
|
|
@classmethod
|
def get_juejin_code_list_with_prefix(cls, codes):
|
list = []
|
for d in codes:
|
if d[0:2] == '00':
|
list.append("SZSE.{}".format(d))
|
elif d[0:2] == '60':
|
list.append("SHSE.{}".format(d))
|
return list
|
|
@classmethod
|
def get_gp_latest_info(cls, codes, fields=None):
|
if not codes:
|
return []
|
symbols = cls.get_juejin_code_list_with_prefix(codes)
|
|
account_id, s_id, token = cls.getJueJinAccountInfo()
|
gmapi.set_token(token)
|
data = gmapi.get_instruments(symbols=",".join(symbols), fields=fields)
|
return data
|
|
@classmethod
|
def get_history_tick_n(cls, code, count, fields=None):
|
symbols = cls.get_juejin_code_list_with_prefix([code])
|
|
account_id, s_id, token = cls.getJueJinAccountInfo()
|
gmapi.set_token(token)
|
# 前除权
|
results = gmapi.history_n(symbol=symbols[0], frequency="1d", count=count, adjust=1, fields=fields)
|
return results
|
|
@classmethod
|
def get_gp_current_info(cls, codes, fields=''):
|
if not codes:
|
return []
|
symbols = cls.get_juejin_code_list_with_prefix(codes)
|
|
account_id, s_id, token = cls.getJueJinAccountInfo()
|
gmapi.set_token(token)
|
data = gmapi.current(symbols=",".join(symbols), fields=fields)
|
return data
|
|
# 获取交易所的代码
|
@classmethod
|
def get_exchanges_codes(cls, exchanges):
|
|
account_id, s_id, token = cls.getJueJinAccountInfo()
|
gmapi.set_token(token)
|
return gmapi.get_instruments(exchanges=exchanges, sec_types=[1], skip_suspended=True, skip_st=True,
|
fields="symbol,sec_type,sec_id,sec_name,listed_date,sec_level,is_suspended,pre_close")
|
|
@classmethod
|
def get_previous_trading_date(cls, date):
|
account_id, s_id, token = cls.getJueJinAccountInfo()
|
gmapi.set_token(token)
|
return gmapi.get_previous_trading_date("SHSE", date)
|
|
@classmethod
|
def get_previous_trading_date_cache(cls, date):
|
if date not in cls.__previous_trading_date_cache:
|
pre_date = cls.get_previous_trading_date(date)
|
if pre_date:
|
cls.__previous_trading_date_cache[date] = pre_date
|
return cls.__previous_trading_date_cache.get(date)
|
|
# 返回指定日期的下个交易日
|
@classmethod
|
def get_next_trading_date(cls, date):
|
|
account_id, s_id, token = cls.getJueJinAccountInfo()
|
gmapi.set_token(token)
|
return gmapi.get_next_trading_date("SHSE", date)
|
|
@classmethod
|
def get_trading_dates(cls, start_date, end_date):
|
account_id, s_id, token = cls.getJueJinAccountInfo()
|
gmapi.set_token(token)
|
return gmapi.get_trading_dates("SHSE", start_date, end_date)
|