请 [注册] 或 [登录]  | 返回主站

量化交易吧 /  数理科学 帖子:3364712 新帖:0

懒人风格:将自己的持仓股票或选股,添加到雪球自选股列表

只求稳定发表于:5 月 10 日 05:59回复(1)

想要观察 策略选股,或持仓股票,以前经常手动添加到APP的自选股列表。
而策略又经常调仓,累啊,于是发扬懒人风格。想办法自动同步策略的持仓到APP里去。
参考了一下easytrader,决定同步到雪球自选股里去
为啥是雪球,纯粹是因为程序容易写,同花顺和腾讯自选股的登录一堆加密,不想整。
具体看研究

import requests
import json
import time


def get_unix_time():
    return int(time.time())

def chang_xq_stocks(stock):
    stock = stock.upper()
    if stock[:2] in ['SH', 'SZ']:
        return stock
    return ('SH' + stock[:6] if stock[-4:] == 'XSHG'    #聚宽代码
            else 'SZ' + stock[:6] if stock[-4:] == 'XSHE'
            else 'SH' + stock if int(stock[0]) >= 5 # 纯股票代码
            else 'SZ' + stock
            )
    
# 雪球自选股操作类
class XqStocks(object):
    def __init__(self, **kwargs):
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0',
            'Host': 'xueqiu.com',
            'Pragma': 'no-cache',
            'Connection': 'keep-alive',
            'Accept': '*/*',
            'Accept-Encoding': 'gzip,deflate,sdch',
            'Cache-Control': 'no-cache',
            'Referer': 'https://xueqiu.com/portfolios',
            'X-Requested-With': 'XMLHttpRequest',
            'Accept-Language': 'zh-CN,zh;q=0.5',
            'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
        }
        self.session = requests.Session()
        self.session.headers.update(headers)
        if 'proxy_ip' in kwargs:
            s = "%s:%s" % (kwargs['proxy_ip'], kwargs.get('proxy_port',808))
            if 'proxy_user' in kwargs and 'proxy_pwd' in kwargs:
                s = '%s:%s@%s' % (kwargs['proxy_user'], kwargs['proxy_pwd'], s)
            self.session.proxies = {
                "http": "http://" + s,
                "https": "https://" + s,
            }
        self.account_config = kwargs
        self.config = {
            'login_api': 'https://xueqiu.com/user/login',
            'stocks': 'https://xueqiu.com/v4/stock/portfolio/stocks.json?size=1000&pid=%d&category=%s&type=%s',
            'poster': 'https://xueqiu.com/service/poster',
            'group_list': 'https://xueqiu.com/v4/stock/portfolio/list.json?system=true'
        }
        self.group_infos = {}
        self.defalut_group_name = kwargs.get('group_name', '')
        self.defalut_group_info = {
             'category': 2,
             'type': 1,
             'id': -1,
             'name': ''
        }
        self.is_logon = False

    # 登录并获取分组信息
    def login(self):
        login_post_data = {
            'username': self.account_config.get('username', ''),
            'areacode': '86',
            'telephone': self.account_config['account'],
            'remember_me': '0',
            'password': self.account_config['password']
        }
        login_response = self.session.post(self.config['login_api'], data=login_post_data)
        login_status = json.loads(login_response.text)
        if 'error_description' in login_status:
            return False
        self.update_group_infos()
        self.is_logon = True
        return True

    # 获取一个分组名的信息dict
    def get_group_params(self, group_name):
        if group_name is None:
            group_name = self.defalut_group_name
        if isinstance(group_name,str):
            group_name = group_name.decode('utf-8')
        if group_name != '':
            if group_name not in self.group_infos.keys():
                self.create_group(group_name)  # 创建分组
                self.update_group_infos()  # 更新分组信息
                if group_name not in self.group_infos.keys():
                    return self.defalut_group_info
        return self.group_infos.get(group_name, self.defalut_group_info)

    # 获取一个分组下的自选股
    def get_stocks(self, group_name=None):
        d = self.get_group_params(group_name)
        stocks = self.session.get(self.config['stocks'] % (
            d.get('id', -1), d.get('category', 1), d.get('type', 1))).text
        stocks = json.loads(stocks)[u'stocks']
        return [x['code'] for x in stocks if (x['exchange'] == 'SH') or (x['exchange'] == 'SZ')]

    # 更新分组信息
    def update_group_infos(self):
        res = self.session.get(self.config['group_list']).text
        res = json.loads(res)[u'portfolios']
        self.group_infos = {}
        for p in res:
            self.group_infos[p['name']] = {'category': p['portfolio']['category'],
                                           'type': p['type'],
                                           'id': p['id'],
                                           'name': p['name']}

    # 创建一个分组
    def create_group(self, group_name):
        post_data = {
            'data[_]': get_unix_time(),
            'data[pname]': group_name,
            'url': '/stock/portfolio/create.json'
        }
        res = self.session.post(self.config['poster'], data=post_data).text
        return json.loads(res)['success']

    # 删除一个分组下的股票 group_name=None时,用参数里的默认分组。==''时为不分组添加
    def del_stock(self, stock, group_name=None):
        post_data = {
            'data[_]': get_unix_time(),
            'data[code]': stock,
            'url': '/stock/portfolio/delstock.json'
        }
        d = self.get_group_params(group_name)
        if d.get('name', '') != '':
            post_data['data[pname]'] = d.get('name', '')
            post_data['data[pids]'] = d.get('type', '')
        res = self.session.post(self.config['poster'], data=post_data).text
        return json.loads(res)['success']

    # 向一个分组下添加股票
    def add_stock(self, stock, group_name=None):
        post_data = {
            'data[_]': get_unix_time(),
            'data[code]': stock,
            'data[isnotice]': 1,
            'data[targetpercent]': 7,
            'url': '/stock/portfolio/addstock.json'
        }
        d = self.get_group_params(group_name)
        if d.get('name', '') != '':
            post_data['data[pnames]'] = d.get('name', '')
            post_data['data[pids]'] = d.get('type', '')
        res = self.session.post(self.config['poster'], data=post_data).text
        return json.loads(res)['success']

    def sync(self, stocks, group_name=None):
        """
        同步一个自选股列表到雪球自选股
        :param stocks: 雪球格式的自选股列表
        :param group_name: 雪球自选股分组名(不存在则自动创建)
        :return: 成功返回 '' 失败返回错误信息
        """
        try:
            if not self.is_logon:
                if not self.login():
                    return u'登录雪球错误'
            stocks = [chang_xq_stocks(x) for x in stocks] # 转成雪球的股票代码列表
            old_s = self.get_stocks(group_name) # 获取雪球分组自选股列表            
            for stock in [x for x in old_s if x not in stocks]:
                self.del_stock(stock, group_name)
            for stock in [x for x in stocks if x not in old_s]:
                self.add_stock(stock, group_name)
            return ''
        except Exception as e:
            return (u'同步雪球错误: %s' % str(e))
# 创建对象
xq = XqStocks(user_name='' # 用户名,一般为''
              , account='XXXXXXXXX' # 登录帐号,一般为手机号
              , password='XXXXXX' # 密码
              , group_name='测试' # 默认操作的自选股的分组名,默认为''
#               , proxy_ip='XXX.XXX.XXX.XXX' # http代码的IP # 不用代理可以不写
#               , proxy_port='808'  # http代理的端口
#               , proxy_user='' # 代理用户名,无需登录的用户名可以不写
#               , proxy_pwd='' # 代理密码
             )
# 单独测试
if not xq.login():
    print '登录错误'
else:
    stocks = xq.get_stocks()
    print '雪球自选股:'
    print stocks
    print '添加股票结果:%s' % xq.add_stock('SH000016')
    print '删除股票结果:%s' % xq.del_stock('SH600392')
    print '测试后雪球自选股:'
    print xq.get_stocks()

    # 同步测试
    stocks = ['000001.XSHE','399678.XSHE','600392.XSHG']
    xq.sync(stocks) # 将雪球自选股列表更新为stocks
    print '同步后雪球自选股:'
    print xq.get_stocks()

    print '获取所有雪球自选股列表'
    print xq.get_stocks('全部')
雪球自选股:
[u'SH600392', u'SZ399678', u'SZ000001']
添加股票结果:True
删除股票结果:True
测试后雪球自选股:
[u'SH000016', u'SZ399678', u'SZ000001']
同步后雪球自选股:
[u'SH600392', u'SZ399678', u'SZ000001']
获取所有雪球自选股列表
[u'SH600392', u'SZ000001', u'SZ399678', u'SZ300699', u'SH601949', u'SZ002857', u'SH603226', u'SH603269', u'SH603090', u'SH603580', u'SZ002865', u'SH603536', u'SH603991', u'SH000001', u'SH603330']
 
 

全部回复

0/140

达人推荐

量化课程

    移动端课程