没有买卖就没有伤害

import pandas as pd
import datetime
from jqdata import *  # 请确保jqdata库可用

DIVIDEND_QUERY_INTERVAL = 1000  # 用于分批查询分红信息的区间长度

def initialize(context):
    # 初始化设置
    log.set_level('order', 'error')
    set_option('use_real_price', True)
    set_benchmark('000905.XSHG')
    # 设置交易成本
    set_order_cost(OrderCost(open_tax=0, close_tax=0.0001, open_commission=0.0003, close_commission=0.0003, close_today_commission=0, min_commission=5), type='fund')
    # 策略全局变量
    g.stock_num = 3
    g.buylist = []

    g.new_high_value = context.portfolio.starting_cash
    g.maxdown = 0
    # 安排日常任务
    run_daily(get_high_limit_stocks, time='9:05', reference_security='000300.XSHG')
    run_monthly(select_stocks_and_buy, 1, time='9:30')
    run_daily(sell_stocks_opened_from_up_limit, time='13:57')
    run_daily(sell_hi_vol_stocks_at_dayend_and_buy_again, time='14:27')
    run_monthly(analyze_stocks_held, 1, time='15:01')

def get_dividend_ratio_filter_list(context, stock_list, sort=True, p1=0.0, p2=1.0):
    # 计算股息率并筛选
    time1 = context.previous_date
    time0 = time1 - datetime.timedelta(days=365)
    
    # 分批查询分红数据
    dividend_list = []
    for i in range(0, len(stock_list), DIVIDEND_QUERY_INTERVAL):
        q = query(finance.STK_XR_XD.code, 
                  finance.STK_XR_XD.a_registration_date, 
                  finance.STK_XR_XD.bonus_amount_rmb
                 ).filter(finance.STK_XR_XD.a_registration_date >= time0,
                          finance.STK_XR_XD.a_registration_date <= time1,
                          finance.STK_XR_XD.code.in_(stock_list[i:i+DIVIDEND_QUERY_INTERVAL]))
        dividend_list.append(finance.run_query(q))
    dividend = pd.concat(dividend_list).fillna(0).groupby('code').sum()
    
    # 获取市值数据
    q = query(valuation.code, valuation.market_cap).filter(valuation.code.in_(stock_list))
    market_cap_data = get_fundamentals(q, date=time1).set_index('code')
    
    # 计算股息率并进行排序筛选
    DR = pd.concat([dividend, market_cap_data], axis=1)
    DR['dividend_ratio'] = (DR['bonus_amount_rmb']/10000) / DR['market_cap']
    DR.sort_values(by='dividend_ratio', ascending=sort, inplace=True)
    
    final_list = DR.index[int(p1*len(DR)):int(p2*len(DR))].tolist()
    return final_list

	

def sell_stocks(context, sell_list):
    current_data=get_current_data()
    if len(sell_list)>0:
        for security in sell_list:
            cprice = current_data[security].last_price
            boughtcost = context.portfolio.positions[security].avg_cost
            if context.portfolio.positions[security].avg_cost==0:
                log.error("Sell %s " % (current_data[security].name), "avg_cost is 0")
                profit = 0
            else:
                profit = (cprice - boughtcost)/boughtcost *100
            log.info("Sell %s " % (current_data[security].name), "profit: %.1f%%" % profit, "init time %s" % context.portfolio.positions[security].init_time)
            limit_price = max(cprice*0.95,current_data[security].low_limit)
            ordert = order_target_value(security,0, LimitOrderStyle(limit_price))
            if (None == ordert):
                log.info("Sell failed %s" % (current_data[security].name))
    #else:
    #    log.info("no one to sell")
    return
################End sell_stocks

# 准备股票池
def get_high_limit_stocks(context):
    #获取已持有列表
    g.high_limit_list = []
    hold_list = list(context.portfolio.positions)
    if hold_list:
        for stock in hold_list:
            df=get_price(stock, count = 1, end_date=context.previous_date, frequency='daily', fields=['high_limit', 'close'])
            if df['high_limit'][-1]==df['close'][-1]:
                g.high_limit_list.append(stock)
#  调整昨日涨停股票
def sell_stocks_opened_from_up_limit(context):
    cdata = get_current_data()
    sell_list = [stock for stock in g.high_limit_list if cdata[stock].last_price < cdata[stock].high_limit]
    for stock in sell_list:
        log.info("[%s]涨停打开,卖出" % cdata[stock].name)
    if sell_list:
        sell_stocks(context, sell_list)

# 尾盘买卖股;放量未涨停的卖出;低位的买进
def sell_hi_vol_stocks_at_dayend_and_buy_again(context):
    btlist = context.portfolio.positions
    cdata = get_current_data()

    stock_vol_info = {
        stock: (now_vol(context, stock), ma_vol(context, stock, 10))
        for stock in btlist
        if cdata[stock].last_price != cdata[stock].high_limit
    }
    sell_list = [stock for stock, vol in stock_vol_info.items() if vol[0] > vol[1] * 3]

    for stock in sell_list:
        log.info("[%s]放量未涨停,卖出" % cdata[stock].name)
        
    if sell_list:
        sell_stocks(context, sell_list)

    buy_stocks(context, g.buylist)

def analyze_stocks_held(context):
    current_data = get_current_data()
    hold_stocks = list(context.portfolio.positions.keys())
    for s in hold_stocks:
        q = query(valuation.code, valuation.market_cap, valuation.pe_ratio, indicator.inc_net_profit_year_on_year).filter(valuation.code == s)
        df = get_fundamentals(q)
        stock_name = current_data[s].name
        if not df.empty:  # 确保df不是空
            pe_ratio = df['pe_ratio'].iloc[0] if not df['pe_ratio'].isnull().all() else 'N/A'
            inc_net_profit_yoy = df['inc_net_profit_year_on_year'].iloc[0] if not df['inc_net_profit_year_on_year'].isnull().all() else 'N/A'
            log.info(f"{s} {stock_name} 市盈率: {pe_ratio}")
            log.info(f"{s} {stock_name} 净利润同比增长率: {inc_net_profit_yoy}")
        else:
            log.info(f"{s} {stock_name} 数据不足,无法提供市盈率或净利润同比增长率。")

    log.info('一天结束')
    log.info('#' * 60)

def after_trading_end(context):
    g.total_value = context.portfolio.total_value
    if g.total_value > g.new_high_value:   
        g.new_high_value = g.total_value  
        g.maxdown = 0
    else:
        g.maxdown = max(g.maxdown, (g.new_high_value - g.total_value) / g.new_high_value * 100)

    record(maxdown=g.maxdown)
    
def select_stocks_and_buy(context):
    select_stocks(context)
    buy_stocks(context, g.buylist)
    
def select_stocks(context):
    dt_last = context.previous_date
    # 假设get_all_securities返回DataFrame
    all_stocks_df = get_all_securities('stock', dt_last)
    stocks = all_stocks_df.index.tolist()
    
    stocks = filter_unwanted_stocks(context, stocks)

    # 获取基本面数据,并按市值排序选择小市值股票
    df = get_fundamentals(query(valuation.code, valuation.market_cap)
                          .filter(valuation.code.in_(stocks),
                                  valuation.market_cap <= 100)
                          .order_by(valuation.market_cap.asc()))
    
    # Update buylist
    g.buylist = df['code'].tolist()[:g.stock_num * 2]

def now_vol(context, stock):   
    
    dt_zero_clock_today = context.current_dt - datetime.timedelta(hours=context.current_dt.hour, minutes=context.current_dt.minute, seconds=context.current_dt.second, microseconds=context.current_dt.microsecond)
    #print ('dt_zero_clock_today', dt_zero_clock_today, type(dt_zero_clock_today))
    dt_trading_start_today = dt_zero_clock_today + datetime.timedelta(hours=9, minutes=15, seconds=00)
    #print ('dt_trading_start_today', dt_trading_start_today, type(dt_trading_start_today))

    df_vol = get_price(stock, start_date=dt_trading_start_today, end_date=context.current_dt, frequency='minute', fields=['volume'])
    ft_now_vol = df_vol['volume'].sum()
    #print (stock, 'ft_now_vol', ft_now_vol)
    return ft_now_vol    
    
def ma_vol(context, stock, number_of_days):   
    df_vol = get_price(stock, end_date=context.previous_date, frequency='daily', count=number_of_days, fields=['volume'])
    ft_ma_vol = df_vol['volume'].mean()
    #print (stock, number_of_days, 'volume mean', ft_ma_vol) 
    return ft_ma_vol    
    
# 用于过滤股票的函数 - 一次过滤所有不需要的股票
def filter_unwanted_stocks(context, stocks):
    current_data = get_current_data()
    last_prices = history(1, unit='1m', field='close', security_list=stocks)
    
    def is_unwanted_stock(stock):
        data = current_data[stock]
        last_price = last_prices[stock][-1]
        # 过滤逻辑
        return any([
            stock[0] == '4' or stock[0] == '8' or stock[:2] == '68', # 科创北交股票
            data.paused, # 停牌股票
            data.is_st or 'ST' in data.name or '*' in data.name or '退' in data.name, # ST股票
            last_price >= data.high_limit or last_price <= data.low_limit, # 涨跌停股票
            last_price >= 9, # 股价高于9元的股票
        ])
    
    return [stock for stock in stocks if not is_unwanted_stock(stock)]

def buy_stocks(context, choice):
    position_count = len(context.portfolio.positions)
    if g.stock_num <= position_count:
        return
    
    psize = context.portfolio.available_cash / (g.stock_num - position_count)
    current_data = get_current_data()
    
    for stock in choice:
        if stock not in context.portfolio.positions:
            log.info('buy', stock, current_data[stock].name)
            order_value(stock, psize)
            if len(context.portfolio.positions) == g.stock_num:
                break
			

=买买===========

import pandas as pd
import datetime
from jqdata import *  # 请确保jqdata库可用

DIVIDEND_QUERY_INTERVAL = 1000  # 用于分批查询分红信息的区间长度

def initialize(context):
    # 初始化设置
    log.set_level('order', 'error')
    set_option('use_real_price', True)
    set_benchmark('000905.XSHG')
    # 设置交易成本
    set_order_cost(OrderCost(open_tax=0, close_tax=0.0001, open_commission=0.0003, close_commission=0.0003, close_today_commission=0, min_commission=5), type='fund')
    # 策略全局变量
    g.stock_num = 3
    g.buylist = []
    # 初始化一个空集合用来跟踪已卖出的股票
    context.stocks_sold_today = set()

    g.new_high_value = context.portfolio.starting_cash
    g.maxdown = 0
    # 安排日常任务
    run_daily(get_high_limit_stocks, time='9:05', reference_security='000300.XSHG')
    run_monthly(select_stocks_and_buy, 1, time='9:30')
    run_daily(sell_stocks_opened_from_up_limit, time='14:00')
    run_daily(sell_hi_vol_stocks_at_dayend_and_buy_again, time='14:30')
    run_monthly(analyze_stocks_held, 1, time='15:01')

def get_dividend_ratio_filter_list(context, stock_list, sort=True, p1=0.0, p2=1.0):
    # 计算股息率并筛选
    time1 = context.previous_date
    time0 = time1 - datetime.timedelta(days=365)
    
    # 分批查询分红数据
    dividend_list = []
    for i in range(0, len(stock_list), DIVIDEND_QUERY_INTERVAL):
        q = query(finance.STK_XR_XD.code, 
                  finance.STK_XR_XD.a_registration_date, 
                  finance.STK_XR_XD.bonus_amount_rmb
                 ).filter(finance.STK_XR_XD.a_registration_date >= time0,
                          finance.STK_XR_XD.a_registration_date <= time1,
                          finance.STK_XR_XD.code.in_(stock_list[i:i+DIVIDEND_QUERY_INTERVAL]))
        dividend_list.append(finance.run_query(q))
    dividend = pd.concat(dividend_list).fillna(0).groupby('code').sum()
    
    # 获取市值数据
    q = query(valuation.code, valuation.market_cap).filter(valuation.code.in_(stock_list))
    market_cap_data = get_fundamentals(q, date=time1).set_index('code')
    
    # 计算股息率并进行排序筛选
    DR = pd.concat([dividend, market_cap_data], axis=1)
    DR['dividend_ratio'] = (DR['bonus_amount_rmb']/10000) / DR['market_cap']
    DR.sort_values(by='dividend_ratio', ascending=sort, inplace=True)
    
    final_list = DR.index[int(p1*len(DR)):int(p2*len(DR))].tolist()
    return final_list

	
def sell_stocks(context, sell_list):
    current_data = get_current_data()
    if len(sell_list) > 0:
        for security in sell_list:
            cprice = current_data[security].last_price
            boughtcost = context.portfolio.positions[security].avg_cost
            if boughtcost == 0:
                log.error("Sell %s " % (current_data[security].name), "avg_cost is 0")
                profit = 0
            else:
                profit = (cprice - boughtcost) / boughtcost * 100
            log.info(
                "Sell %s " % (current_data[security].name),
                "profit: %.1f%%" % profit,
                "init time %s" % context.portfolio.positions[security].init_time,
            )
            limit_price = max(cprice * 0.95, current_data[security].low_limit)
            order_id = order_target_value(security, 0, style=LimitOrderStyle(limit_price))
            if order_id is not None:
                # 记录成功卖出的股票
                context.stocks_sold_today.add(security)
            else:
                log.info("Sell failed %s" % (current_data[security].name))
    # else:
    #     log.info("no one to sell")
    return
################End sell_stocks

# 准备股票池
def get_high_limit_stocks(context):
    #获取已持有列表
    g.high_limit_list = []
    hold_list = list(context.portfolio.positions)
    if hold_list:
        for stock in hold_list:
            df=get_price(stock, count = 1, end_date=context.previous_date, frequency='daily', fields=['high_limit', 'close'])
            if df['high_limit'][-1]==df['close'][-1]:
                g.high_limit_list.append(stock)
#  调整昨日涨停股票
def sell_stocks_opened_from_up_limit(context):
    cdata = get_current_data()
    sell_list = [stock for stock in g.high_limit_list if cdata[stock].last_price < cdata[stock].high_limit]
    for stock in sell_list:
        log.info("[%s]涨停打开,卖出" % cdata[stock].name)
    if sell_list:
        sell_stocks(context, sell_list)

# 尾盘买卖股;放量未涨停的卖出;低位的买进
def sell_hi_vol_stocks_at_dayend_and_buy_again(context):
    btlist = context.portfolio.positions
    cdata = get_current_data()

    stock_vol_info = {
        stock: (now_vol(context, stock), ma_vol(context, stock, 10))
        for stock in btlist
        if cdata[stock].last_price != cdata[stock].high_limit
    }
    sell_list = [stock for stock, vol in stock_vol_info.items() if vol[0] > vol[1] * 3]

    for stock in sell_list:
        log.info("[%s]放量未涨停,卖出" % cdata[stock].name)
        
    if sell_list:
        sell_stocks(context, sell_list)

    buy_stocks(context, g.buylist)

def analyze_stocks_held(context):
    current_data = get_current_data()
    hold_stocks = list(context.portfolio.positions.keys())
    for s in hold_stocks:
        q = query(valuation.code, valuation.market_cap, valuation.pe_ratio, indicator.inc_net_profit_year_on_year).filter(valuation.code == s)
        df = get_fundamentals(q)
        stock_name = current_data[s].name
        if not df.empty:  # 确保df不是空
            pe_ratio = df['pe_ratio'].iloc[0] if not df['pe_ratio'].isnull().all() else 'N/A'
            inc_net_profit_yoy = df['inc_net_profit_year_on_year'].iloc[0] if not df['inc_net_profit_year_on_year'].isnull().all() else 'N/A'
            log.info(f"{s} {stock_name} 市盈率: {pe_ratio}")
            log.info(f"{s} {stock_name} 净利润同比增长率: {inc_net_profit_yoy}")
        else:
            log.info(f"{s} {stock_name} 数据不足,无法提供市盈率或净利润同比增长率。")

    log.info('一天结束')
    log.info('#' * 60)

def after_trading_end(context):
    g.total_value = context.portfolio.total_value
    if g.total_value > g.new_high_value:   
        g.new_high_value = g.total_value  
        g.maxdown = 0
    else:
        g.maxdown = max(g.maxdown, (g.new_high_value - g.total_value) / g.new_high_value * 100)

    record(maxdown=g.maxdown)
    
def select_stocks_and_buy(context):
    select_stocks(context)
    buy_stocks(context, g.buylist)
    
def select_stocks(context):
    dt_last = context.previous_date
    # 假设get_all_securities返回DataFrame
    all_stocks_df = get_all_securities('stock', dt_last)
    stocks = all_stocks_df.index.tolist()
    
    stocks = filter_unwanted_stocks(context, stocks)

    # 获取基本面数据,并按市值排序选择小市值股票
    df = get_fundamentals(query(valuation.code, valuation.market_cap)
                          .filter(valuation.code.in_(stocks),
                                  valuation.market_cap <= 100)
                          .order_by(valuation.market_cap.asc()))
    
    # Update buylist
    g.buylist = df['code'].tolist()[:g.stock_num * 2]

def now_vol(context, stock):   
    
    dt_zero_clock_today = context.current_dt - datetime.timedelta(hours=context.current_dt.hour, minutes=context.current_dt.minute, seconds=context.current_dt.second, microseconds=context.current_dt.microsecond)
    #print ('dt_zero_clock_today', dt_zero_clock_today, type(dt_zero_clock_today))
    dt_trading_start_today = dt_zero_clock_today + datetime.timedelta(hours=9, minutes=15, seconds=00)
    #print ('dt_trading_start_today', dt_trading_start_today, type(dt_trading_start_today))

    df_vol = get_price(stock, start_date=dt_trading_start_today, end_date=context.current_dt, frequency='minute', fields=['volume'])
    ft_now_vol = df_vol['volume'].sum()
    #print (stock, 'ft_now_vol', ft_now_vol)
    return ft_now_vol    
    
def ma_vol(context, stock, number_of_days):   
    df_vol = get_price(stock, end_date=context.previous_date, frequency='daily', count=number_of_days, fields=['volume'])
    ft_ma_vol = df_vol['volume'].mean()
    #print (stock, number_of_days, 'volume mean', ft_ma_vol) 
    return ft_ma_vol    
    
# 用于过滤股票的函数 - 一次过滤所有不需要的股票
def filter_unwanted_stocks(context, stocks):
    current_data = get_current_data()
    last_prices = history(1, unit='1m', field='close', security_list=stocks)
    
    def is_unwanted_stock(stock):
        data = current_data[stock]
        last_price = last_prices[stock][-1]
        # 过滤逻辑
        return any([
            stock[0] == '4' or stock[0] == '8' or stock[:2] == '68', # 科创北交股票
            data.paused, # 停牌股票
            data.is_st or 'ST' in data.name or '*' in data.name or '退' in data.name, # ST股票
            last_price >= data.high_limit or last_price <= data.low_limit, # 涨跌停股票
            last_price >= 9, # 股价高于9元的股票
        ])
    
    return [stock for stock in stocks if not is_unwanted_stock(stock)]

def buy_stocks(context, choice):
    position_count = len(context.portfolio.positions)
    if g.stock_num <= position_count:
        return

    psize = context.portfolio.available_cash / (g.stock_num - position_count)
    current_data = get_current_data()
    
    for stock in choice:
        # 检查是否持有股票,并且当天没有卖出过
        if stock not in context.portfolio.positions and stock not in context.stocks_sold_today:
            log.info('buy', stock, current_data[stock].name)
            order_value(stock, psize)
            # 断言:确保函数在持仓达到期望数量后停止买入
            if len(context.portfolio.positions) == g.stock_num:
                break
            
			

你可能感兴趣的:(windows)