分类 *.py 下的文章

import requests
import json


class Feishu:
    def __init__(self):
        self.app_id = 'cli_9fd1bdc4cfee500e'
        self.app_secret = '你的 Secret'

    def get_token(self):
        payload = {
            'app_id': self.app_id,
            'app_secret': self.app_secret,
        }
        r = requests.post(
            'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal/', data=payload)
        return r.json()['tenant_access_token'] if r.ok else ''

    def send_msg(self, title='hello', content='world'):
        token = self.get_token()
        headers = {
            'Authorization': 'Bearer %s' % token,
            'Content-Type': 'application/json'
        }
        msg = {
            "chat_id": "oc_6fdbd9480850cdf0cdacd6bce1fa9705",
            "msg_type": "post",
            "content": {
                "post": {
                    "zh_cn": {
                        "title": title,
                        "content": [
                            [
                                {
                                    "tag": "text",
                                    "un_escape": True,
                                    "text": content
                                }
                            ]
                        ]
                    }
                }
            }
        }

        print(json.dumps(msg))

        res = requests.post(
            'https://open.feishu.cn/open-apis/message/v4/send/', headers=headers, json=msg)
        print(res.json())
        return True


feishu = Feishu()
feishu.send_msg(title='你好', content='world')

写好了。

思路

通过聚宽平台提供的数据接口,跟踪北向资金出入数据,追涨来实现套利。代码获取了每日的北向流入额,然后用 150 日的流入额做出了一个布林带,当流入额大于等于布林带上轨的时候,策略会跟踪北向持仓中股票自身占比最大的 15 只股票,然后把他们买入,并且卖出自己持仓中不在这 15 只股票。当流入额小于等于布林带下轨时,清仓卖出。

代码

from jqdata import *
import random
import pandas as pd
import numpy as np
import datetime as dt

# 初始化函数,设定基准等等
def initialize(context):
    # 设定沪深300作为基准
    set_benchmark('000300.XSHG')
    # 开启动态复权模式(真实价格)
    set_option('use_real_price', True)
    # 输出内容到日志 log.info()
    log.info('初始函数开始运行且全局只运行一次')
    # 过滤掉order系列API产生的比error级别低的log
    log.set_level('order', 'error')

    ### 股票相关设定 ###
    # 股票类每笔交易时的手续费是:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税, 每笔交易佣金最低扣5块钱
    set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5),
                   type='stock')
    g.max_stock_count = 15
    g.buy_pool = []
    g.sale_pool = []
    g.top_money_in = []
    g.window = 90
    g.stdev_n = 1
    g.mf, g.upper, g.lower = None, None, None
    run_daily(before_market_open, time='07:00')
    run_daily(reblance, '9:30')

def before_market_open(context):
    g.buy_pool = []
    g.sale_pool = []
    pre_date = (context.current_dt - datetime.timedelta(1)
                ).strftime('%Y-%m-%d')
    g.mf, g.upper, g.lower = get_boll(pre_date)
    log.info('北上资金均值:%.2f  北上资金上界:%.2f 北上资金下界:%.2f' % (g.mf, g.upper, g.lower))

def get_boll(end_date):
    """
    获取北向资金布林带
    """
    # 数据表:北上资金某日成交额
    table = finance.STK_ML_QUOTA
    # 查询:日期,每日额度,每日余额
    q = query(
        table.day, table.quota_daily, table.quota_daily_balance
    ).filter(
        table.link_id.in_(['310001', '310002']), table.day <= end_date
    ).order_by(table.day)
    money_df = finance.run_query(q)
    # 每日额度 - 每日余额
    money_df['net_amount'] = money_df['quota_daily'] - \
        money_df['quota_daily_balance']
    # 分组求和
    money_df = money_df.groupby('day')[['net_amount']].sum().iloc[-g.window:]
    mid = money_df['net_amount'].mean()
    stdev = money_df['net_amount'].std()
    upper = mid + 1*g.stdev_n * stdev
    lower = mid - 0.17*g.stdev_n * stdev
    mf = money_df['net_amount'].iloc[-1]
    return mf, upper, lower

def calc_change(context):
    # 数据表:北上资金持有股票数据
    table = finance.STK_HK_HOLD_INFO
    # 查询:日期,名称,代码,持股比例
    q = query(table.day, table.name, table.code, table.share_ratio).filter(
        table.link_id.in_(['310001', '310002']), table.day.in_([context.previous_date]))
    # 获取查询数据结果
    df = finance.run_query(q)
    # 将结果数据集根据持股比例进行降序排序,选出前x只股,x即为 g.max_stock_count 的值,返回结果
    return df.sort_values(by='share_ratio', ascending=False)[:g.max_stock_count]['code'].values

### 每日比较算法 ###
def reblance(context):
    if g.mf >= g.upper:
        s_change_rank = calc_change(context)
        final = list(s_change_rank)
        current_hold_funds_set = set(context.portfolio.positions.keys())
        if set(final) != current_hold_funds_set:
            need_buy = set(final).difference(current_hold_funds_set)
            need_sell = current_hold_funds_set.difference(final)
            cash_per_fund = context.portfolio.total_value/g.max_stock_count*0.99
            for fund in need_sell:
                # order_target(fund, 0)
                add_to_sale_pool(fund)
            for fund in need_buy:
                # order_value(fund, cash_per_fund)
                add_to_buy_pool(fund, cash_per_fund)
        

    elif g.mf <= g.lower:
        current_hold_funds_set = set(context.portfolio.positions.keys())
        if len(current_hold_funds_set) != 0:
            for fund in current_hold_funds_set:
                #log.info('买入 %s' % fund.name)
                # order_target(fund, 0)
                add_to_sale_pool(fund)
           
### 当天卖出队列 ###
def add_to_sale_pool(security_code):
    if len(g.sale_pool) <= g.max_stock_count:
        g.sale_pool.append(security_code)
    
### 当天买入队列 ###
def add_to_buy_pool(security_code, cash):
    if len(g.sale_pool) <= g.max_stock_count:
        g.buy_pool.append({'code': security_code, 'cash': cash})
        log.info(g.buy_pool)

### 买卖策略 ###
'''
测试时暂时空仓
'''
def handle_data(context):
    if len(g.buy_pool) > 0:
        length = len(g.buy_pool)
        idx = 0
        while length > 0:
            buy_item = g.buy_pool[idx]
            order_value(buy_item['code'], buy_item['cash'])
            del g.buy_pool[idx]
            length = length - 1

    elif len(g.sale_pool) > 0:
        length = len(g.sale_pool)
        idx = 0
        while length > 0:
            sale_code = g.sale_pool[idx]
            order_target(sale_code, 0)
            del g.sale_pool[idx]
            length = length - 1