# -*- coding: utf-8 -*- import abc import datetime import re,json import time from typing import List import requests from log import logger from misc import parse_cookies_str class BaseFollower(metaclass=abc.ABCMeta): """ slippage: 滑点,取值范围为 [0, 1] """ LOGIN_PAGE = "" LOGIN_API = "" TRANSACTION_API = "" CMD_CACHE_FILE = "cmd_cache.pk" WEB_REFERER = "" WEB_ORIGIN = "" def __init__(self): #self.trade_queue = queue.Queue() #self.expired_cmds = set() self.s = requests.Session() self.s.verify = False self.slippage: float = 0.0 def login(self, user=None, password=None, **kwargs): """ 雪球登陆, 需要设置 cookies :param cookies: 雪球登陆需要设置 cookies, 具体见 https://smalltool.github.io/2016/08/02/cookie/ :return: """ cookies = kwargs.get("cookies") if cookies is None: raise TypeError( "雪球登陆需要设置 cookies, 具体见" "https://smalltool.github.io/2016/08/02/cookie/" ) headers = self._generate_headers() self.s.headers.update(headers) self.s.get(self.LOGIN_PAGE) cookie_dict = parse_cookies_str(cookies) self.s.cookies.update(cookie_dict) #extract_strategy_name(self, 'ZH1332574') logger.info("登录成功") def _generate_headers(self): headers = { "Accept": "application/json, text/javascript, */*; q=0.01", "Accept-Encoding": "gzip, deflate, br", "Accept-Language": "en-US,en;q=0.8", "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) " "AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/54.0.2840.100 Safari/537.36", "Referer": self.WEB_REFERER, "X-Requested-With": "XMLHttpRequest", "Origin": self.WEB_ORIGIN, "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", } return headers def check_login_success(self, rep): """检查登录状态是否成功 :param rep: post login 接口返回的 response 对象 :raise 如果登录失败应该抛出 NotLoginError """ pass def create_login_params(self, user, password, **kwargs) -> dict: """生成 post 登录接口的参数 :param user: 用户名 :param password: 密码 :return dict 登录参数的字典 """ return {} def extract_strategy_name(self, strategy_url): """ 抽取 策略名,主要用于日志打印,便于识别 :param strategy_url: :return: str 策略名 """ pass #新增 def _query_zh_(self,userid): url = 'https://im.xueqiu.com/im-comet/v2/sessions/1681984443-0/messages.json?user_id=%s&limit=%d' %(userid, 1) chat_history = self.s.get(url).json() for chat_record in chat_history: new=chat_record['messageId']#获取messageId messageType=chat_record['messageType']#获取messageId starte='1' if messageType=='VIEW': view1 = json.loads(chat_record['view'])#策略代号 starte=view1['url'][21:] #策略代号 time.sleep(1) return new,starte #非开盘时间调仓,补充 def minutes_2(self, strategys, userid, assets,**kwargs): dayOfWeek = datetime.datetime.now().weekday() time_n=datetime.datetime.now() hour=str(time_n)[11:13] minute=int(str(time_n)[14:16]) print(time_n) if dayOfWeek<=4 and ((hour=='09' and minute<32 and minute>=30) or (hour=='13' and minute<2)) : #if dayOfWeek<=6 or (hour=='11' or minute<=59): for j in range(0,len(strategys)): print('开盘自动监测中......',strategys[j]) try: transactions = self.query_strategy_transaction(strategys[j], assets[j],**kwargs) if len(transactions)>0: return transactions except Exception as e: #logger.exception("无法获取策略 %s 调仓信息, 错误: %s, 跳过此次调仓查询", name, e) time.sleep(3) if j < len(strategys)-1: continue else: return [] else: return [] def track_strategy_worker(self, strategys, userid,users, assets, interval=10, **kwargs): """跟踪下单worker :param strategy: 策略id :param name: 策略名字 :param interval: 轮询策略的时间间隔,单位为秒""" old,starte=self._query_zh_(userid) transactions=[] k=0 while True: k=k+1 print(k) if k>=100: return [] #前两分钟补充,非开盘调仓 minutes_2_data=self.minutes_2( strategys, userid, assets,**kwargs) if not minutes_2_data is None and len(minutes_2_data)>0: return minutes_2_data try: new,starte_n=self._query_zh_(userid)#新增 except: time.sleep(5) for j in range(0,len(strategys)): print('自动监测中......',strategys[j]) if new != old and starte_n==strategys[j]: #if new == old: old=new try: transactions = self.query_strategy_transaction(strategys[j], assets[j],**kwargs) if len(transactions)>0: k=5 return transactions if k==5: break except Exception as e: logger.exception("无法获取策略 %s 调仓信息, 错误: %s, 跳过此次调仓查询", e) time.sleep(3) continue def query_strategy_transaction(self, strategy,assets, **kwargs): params = self.create_query_transaction_params(strategy) rep = self.s.get(self.TRANSACTION_API, params=params) history = rep.json() transactions = self.extract_transactions(history) return self.project_transactions(transactions,assets, **kwargs) def extract_transactions(self, history) -> List[str]: """ 抽取接口返回中的调仓记录列表 :param history: 调仓接口返回信息的字典对象 :return: [] 调参历史记录的列表 """ return [] def create_query_transaction_params(self, strategy) -> dict: """ 生成用于查询调参记录的参数 :param strategy: 策略 id :return: dict 调参记录参数 """ return {} def project_transactions(self, transactions, **kwargs): """ 修证调仓记录为内部使用的统一格式 :param transactions: [] 调仓记录的列表 :return: [] 修整后的调仓记录 """ pass