金字塔决策交易系统

 找回密码
 

微信登录

微信扫一扫,快速登录

搜索
查看: 748|回复: 1

老师,麻烦把这个模型改成股票多头自动交易。多谢了。

[复制链接]

5

主题

23

帖子

23

积分

Rank: 1

等级: 新手上路

注册:
2022-8-21
曾用名:
发表于 2022-11-18 19:51 | 显示全部楼层 |阅读模式
from jqdata import *
import pandas as pd
from jqfactor import *
import numpy as np
import datetime

# 初始化函数,设定基准等等
def initialize(context):
    set_option("avoid_future_data", True)
    # 设定沪深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')

    ## 运行函数(reference_security为运行时间的参考标的;传入的标的只做种类区分,因此传入'000300.XSHG'或'510300.XSHG'是一样的)
    # 开盘前运行
    run_daily(before_market_open, time='before_open', reference_security='000300.XSHG')
    # 开盘时运行
    # run_daily(market_open, time='open', reference_security='000300.XSHG')
    # 收盘后运行
    run_daily(buy_or_sell, time='every_bar', reference_security='000300.XSHG')

    g.stock_list = []


def get_income_profit():
    q = query(
        indicator
    ).filter(
    )
    df = get_fundamentals(q)
    inc_total_revenue_year_on_year = {}
    inc_operation_profit_year_on_year = {}
    for index, row in df.iterrows():
        code = row['code']
        inc_total_revenue_year_on_year[code] = row['inc_total_revenue_year_on_year']
        inc_operation_profit_year_on_year[code] = row['inc_operation_profit_year_on_year']
    return inc_total_revenue_year_on_year, inc_operation_profit_year_on_year


def set_feasible_stocks(context, stock_list):
    set_universe(stock_list)
    current_data = get_current_data()
    stock_list_after_filter = []
    inc_total_revenue_year_on_year, inc_operation_profit_year_on_year = get_income_profit()
    st_dict = get_extras('is_st', stock_list, start_date=context.previous_date, end_date=context.previous_date,
                         df=True)

    # filter  paused / st / hight limit / low limit / bad profit
    for stock in stock_list:
        if st_dict[stock][0]:
            #log.info('stock %s st', stock)
            continue

        if inc_total_revenue_year_on_year.get(stock, -1) < 0:
            # log.info('inc_total_revenue_year_on_year not good')
            continue
        if inc_operation_profit_year_on_year.get(stock, -1) < 0:
            # log.info('inc_operation_profit_year_on_year not good')
            continue

        stock_list_after_filter.append(stock)
    # filter bad profit

    return stock_list_after_filter


def get_index_percent(context):
    end_date = context.previous_date
    start_date = end_date - datetime.timedelta(days=366)
    # 获取最近60天的指数数据
    sh_index = {}
    sz_index = {}
    price_list = get_price('000001.XSHG', start_date=start_date, end_date=end_date)
    last_value = 0
    for index, row in price_list.iterrows():
        if last_value == 0:
            last_value = row['close']
            continue
        sh_index[index] = round(((row['close'] - last_value) / last_value) * 100, 3)
        last_value = row['close']

    price_list = get_price('399001.XSHE', start_date=start_date, end_date=end_date)
    last_value = 0
    for index, row in price_list.iterrows():
        if last_value == 0:
            last_value = row['close']
            continue
        sz_index[index] = round(((row['close'] - last_value) / last_value) * 100, 3)
        last_value = row['close']
    return sh_index, sz_index


def get_stock_percent(context, stock_list):
    stock_percent = {}
    stock_last_prict = {}
    end_date = context.previous_date
    start_date = end_date - datetime.timedelta(days=366)
    price_list = get_price(stock_list, start_date=start_date, end_date=end_date, frequency='daily')
    close_price_list = price_list['close']
    for index, row in close_price_list.iterrows():
        for code in close_price_list.columns:
            if not (code in stock_percent.keys()):
                stock_percent[code] = {}
            last_price = stock_last_prict.get(code, 0)
            stock_last_prict[code] = row[code]
            if last_price == 0:
                continue
            stock_percent[code][index] = round(((row[code] - last_price) / last_price) * 100, 3)
    #log.info(stock_percent[stock_list[0]])
    return stock_percent


def calculate_strong_factor(context, stock_list):
    stock_factor_list = {}
    #end_date = context.previous_date
    #start_date = end_date - datetime.timedelta(days=61)

    previous_date_timestamp = pd.Timestamp(context.previous_date)
    # 获取最近60天的指数数据和股票行情数据
    log.info('start get data')
    sh_index, sz_index = get_index_percent(context)
    log.info('finish get index')
    stock_percent_dict = get_stock_percent(context, stock_list)
    log.info('finish get stock')
    for stock in stock_list:
        current_stock_data = stock_percent_dict.get(stock, None)
        if not current_stock_data:
            #log.info('stock %s has not data', stock)
            continue
        # 过滤涨跌盘
        if (current_stock_data[previous_date_timestamp] > 9) or (current_stock_data[previous_date_timestamp] < -9):
            #log.info('The previous date change too much %s', stock)
            continue
        #过滤过去10天涨跌幅度过大的股票
        previe_ten_percent = 0
        for i in range(10):
            current_dt = context.previous_date - datetime.timedelta(days=i)
            current_timestamp = pd.Timestamp(current_dt)
            current_percent = current_stock_data.get(current_timestamp, 0)
            if current_percent < 0:
                current_percent = -current_percent
            if ( stock == '603189.XSHG'):
                log.info(current_stock_data.get(current_timestamp, 0))
            previe_ten_percent += current_percent
        if (stock == '603189.XSHG'):
            log.info('previe_ten_percent %s' % previe_ten_percent)
        if (previe_ten_percent >= 30):
            log.info('The previous date change too much %s', stock)
            continue

        tmp_index = sh_index
        if stock.endswith('.XSHE'):
            tmp_index = sz_index
        count_good = 0
        count_bad = 0
        # 计算factor
        for key, value in current_stock_data.items():
            if value > tmp_index.get(key, 0):
                count_good += 1
            else:
                count_bad += 1
        stock_factor_list[stock] = count_good / (count_bad + count_good)
    #log.info(stock_factor_list)
    stock_after_sorted = sorted(stock_factor_list.items(), key=lambda d: d[1], reverse=True)
    stock_after_sorted_100 = stock_after_sorted[0:100]
    #log.info(stock_after_sorted_100)
    #return stock_after_sorted[0:100]
    stock_factor_list_100 = {}
    ts_21 = pd.Timestamp(context.previous_date - datetime.timedelta(days=21))
    #按最近20天再重新排序
    for stock, value in stock_after_sorted_100:
        current_stock_data = stock_percent_dict.get(stock, None)
        tmp_index = sh_index
        if stock.endswith('.XSHE'):
            tmp_index = sz_index
        count_good = 0
        count_bad = 0
        # 计算factor
        for key, value in current_stock_data.items():
            if key < ts_21:
                continue
            if value > tmp_index.get(key, 0):
                count_good += 1
            else:
                count_bad += 1
        stock_factor_list_100[stock] = count_good / (count_bad + count_good)
    stock_100_after_sorted = sorted(stock_factor_list_100.items(), key=lambda d: d[1], reverse=True)
    #log.info(stock_100_after_sorted)
    return [stock for stock, value in stock_100_after_sorted[0:10]]

def get_avg_price(context, stock):
    end_date = context.previous_date
    start_date = end_date - datetime.timedelta(days=5)
    stock_price_list = get_price(stock, start_date=start_date, end_date=end_date, frequency='daily')
    count = 0
    max_price = 0
    min_price = 1000000
    total_price = 0
    for index, row in stock_price_list.iterrows():
        current_price = row['close']
        total_price += current_price
        if current_price>max_price:
            max_price = current_price
        if current_price < min_price:
            min_price = current_price
        count += 1
    avg_price = total_price / count
    up_percent = ((max_price - avg_price) / avg_price) * 100
    down_percent = ((avg_price - min_price) / avg_price) * 100
    if (up_percent > 10) or ( up_percent < 2 ):
        log.info('up_percent of stock %s is %s' % (stock, up_percent))
        return (False, avg_price)
    if (down_percent>10) or (down_percent<2):
        log.info('down_percent of stock %s is %s' % (stock, down_percent))
        return (False, avg_price)
    return (True, avg_price)


def before_market_open(context):
    log.info('before_market_open:' + str(context.current_dt.time()))
    # get all stock
    stock_list = list(get_all_securities(['stock']).index)
    log.info('stocks length: %s', len(stock_list))

    # 过滤上市时间小于120天的股票
    for stock in stock_list:
        days_public = (context.current_dt.date() - get_security_info(stock).start_date).days
        if days_public < 120:
            stock_list.remove(stock)

    # filter  paused / st / hight limit / low limit / bad profit
    stock_list = set_feasible_stocks(context, stock_list)
    log.info('stocks length after filter: %s', len(stock_list))

    g.stock_list = stock_list
    g.previous_date = context.previous_date
    values = calc_factors(g.stock_list,
                          [FinanacialFactor()],
                          context.previous_date,
                          context.previous_date)

    factor_dict = values['financial_factor'].ix[0].to_dict()
    factor_after_sorted = sorted(factor_dict.items(), key=lambda d: d[1], reverse=False)
    #print(factor_after_sorted)
    g.stock_list_select = []
    for stock, value in factor_after_sorted[0:500]:
        g.stock_list_select.append(stock)
    #print(g.stock_list_select)

    # get top 100
    g.stock_list = calculate_strong_factor(context, g.stock_list_select)
    g.sell_list = {}
    g.buy_list = {}
    g.position_list = []
    g.stop_loss ={}
    #计算卖出点
    for position_stock, position_info in context.portfolio.positions.items():
        g.position_list.append(position_stock)
        bug_flag, avg_price = get_avg_price(context, position_stock)
        g.sell_list[position_stock] = avg_price * 1.03
        avg_cost = position_info.avg_cost
        if avg_price < (avg_cost*0.95):
            g.stop_loss[position_stock] = True
        else:
            g.stop_loss[position_stock] = False
    #计算买入点
    for stock in g.stock_list:
        bug_flag, avg_price = get_avg_price(context, stock)
        if not bug_flag:
            continue
        g.buy_list[stock] = avg_price * 0.97
    set_universe(g.stock_list)

# buy or sell stocks
def buy_or_sell(context):
    log.info('start buy or sell')
    buy_percent = 3
    #current_data = get_current_data()
    cash = context.portfolio.available_cash
    start_cash = context.portfolio.starting_cash

    for position_stock, position_info in context.portfolio.positions.items():
        #log.info('check sell %s' % position_stock)
        current_price = position_info.price
        total_amount = position_info.total_amount
        avg_cost = position_info.avg_cost
        init_time = position_info.init_time.date()
        avg_check_win_price = avg_cost * 1.07
        if not g.sell_list.get(position_stock, None):
            continue
        position_time = (context.previous_date-init_time).days
        if position_time < 5:
            check_win_price = g.sell_list[position_stock] if g.sell_list[position_stock] > avg_check_win_price else avg_check_win_price
        else:
            check_win_price = g.sell_list[position_stock] if g.sell_list[position_stock] < avg_check_win_price else avg_check_win_price

        if ((((g.sell_list[position_stock] - current_price) / g.sell_list[position_stock]) * 100) > 10) and g.stop_loss[position_stock]:
            order(position_stock, -total_amount)
            log.info('sell stock %s, price: %s, amount: %s' % (position_stock, current_price, total_amount))
            continue
        if current_price > check_win_price:
            order(position_stock, -total_amount)
            log.info('sell stock %s, price: %s, amount: %s' % (position_stock, current_price, total_amount))

    if cash < start_cash/buy_percent:
        return

    for stock in g.stock_list:
        #log.info('check buy %s', stock)
        if stock in g.position_list:
            continue
        if g.buy_list.get(stock, 0) <= 0:
            continue
        current_price = get_current_tick(stock)
        if not current_price:
            continue
        if current_price['current'] < g.buy_list[stock]:
            buy_volumn = int(((start_cash/buy_percent) / current_price['current']) / 100)
            order(stock, buy_volumn*100)
            log.info('buy stock %s, price: %s, volumn: %s' % (stock, current_price['current'], buy_volumn))
            g.position_list.append(stock)


class FinanacialFactor(Factor):
    # 设置因子名称
    name = 'financial_factor'
    # 设置获取数据的时间窗口长度
    max_window = 1
    # 设置依赖的数据,即前四季度的营业收入
    dependencies = ['eps_ttm',  #每股收益
                    'net_asset_per_share', #每股净资产
                    #'operating_revenue_growth_rate', #营业收入增长率
                    #'net_profit_growth_rate', #静利润增长率
                    'inc_total_revenue_year_on_year',
                    'inc_net_profit_year_on_year',
                    'inc_total_revenue_year_on_year_1',
                    'inc_net_profit_year_on_year_1',
                    'inc_total_revenue_year_on_year_2',
                    'inc_net_profit_year_on_year_2',
                    'inc_total_revenue_year_on_year_3',
                    'inc_net_profit_year_on_year_3',
                    'inc_total_revenue_year_on_year_4',
                    'inc_net_profit_year_on_year_4',
                    ]

    def get_sorted(self, input_dict):
        dict_after_sorted = {}
        for index, row in input_dict.iterrows():
            for key,value in row.items():
                if np.isnan(value):
                    row[key] = 0
            row_after_sort = sorted(row.items(), key=lambda d: d[1], reverse=True)
            print(row_after_sort)
            count = 1
            for key,value in row_after_sort:
                dict_after_sorted[key] = count
                count += 1
            break
        print(dict_after_sorted)
        return dict_after_sorted

    def get_cur_price(self):
        all_price = get_price(g.stock_list, start_date=g.previous_date, end_date=g.previous_date)
        return all_price['close']

    def cal_revenue(self, data, key):
        result = (abs(data[key]) / data[key]) * pow(abs(data[key]), 0.5)
        for i in range(1, 5):
            tmp_key = key + '_' + str(i)
            result += (abs(data[tmp_key]) / data[tmp_key]) * pow(abs(data[tmp_key]), 0.5)
        print(result)
        return result

    def calc(self, data):
        #close_pricce = self.get_cur_price()
        inc_total_revenue_year_on_year = self.cal_revenue(data, 'inc_total_revenue_year_on_year')
        inc_net_profit_year_on_year = self.cal_revenue(data, 'inc_net_profit_year_on_year')
        eps_ttm = data['eps_ttm'] #/ close_pricce
        net_asset_per_share = data['net_asset_per_share'] #/ close_pricce
        eps_ttm_sorted = self.get_sorted(eps_ttm)
        net_asset_per_share_sorted = self.get_sorted(net_asset_per_share)
        inc_total_revenue_year_on_year_sorted = self.get_sorted(inc_total_revenue_year_on_year)
        inc_net_profit_year_on_year_sorted = self.get_sorted(inc_net_profit_year_on_year)
        final_result ={}
        for stock in g.stock_list:
            final_result[stock] = (eps_ttm_sorted[stock] + net_asset_per_share_sorted[stock]
                                   + inc_total_revenue_year_on_year_sorted[stock] + inc_net_profit_year_on_year_sorted[stock] ) / 4
        return pd.Series(final_result)

回复

使用道具 举报

37

主题

9972

帖子

6万

积分

Rank: 8Rank: 8

等级: 超级版主

注册:
2021-5-18
曾用名:
wenarm
发表于 2022-11-20 20:06 | 显示全部楼层
python相关策略的转换不在技术支持的范畴之内。python我们只协助用户解决交易接口相关的使用问题。
金字塔提供一对一VIP专业技术指导服务,技术团队实时响应您的日常使用问题与策略编写。联系电话:021-20339086
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 微信登录

本版积分规则

手机版|小黑屋|上海金之塔信息技术有限公司 ( 沪ICP备13035422号 )

GMT+8, 2025-6-9 06:25 , Processed in 0.148719 second(s), 21 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表