Open DrPepper8888 opened 7 months ago
import pandas as pd # 交易假设 INITIAL_CAPITAL = 100000 # 初始资金为 100,000 美元 FEE_RATE = 0.03 / 100 # 交易费用为0.03% TAX_RATE = 0.1 / 100 # 税率为净收入的0.1% # 假设数据已加载并处理成如下形式的DataFrame # pivot_df 行索引是trans_date,列索引是ticker,值value为num,num的正负代表buy/sell # trans_df 第一列是trans_date,第二列是ticker,第三列是num,num的正负代表buy/sell,第四列是当天该ticker的adj_price,第五列是该交易的profit(正就是赚钱了,负是cost或者亏钱),第六列是当前现金cash # holding_df 行索引是trans_date,列索引是ticker,值value为num,num的正负代表buy/sell # price_df 行索引是trans_date,列索引是ticker,值value为adj_price def calculate_profit(ticker, num, adj_close, fee_rate=FEE_RATE): """计算交易利润""" profit = num * adj_close * (1 - fee_rate) if num > 0 else num * adj_close * (1 + fee_rate) return profit def adjust_holding(holding_df, ticker, num, adj_close, date): """调整持仓记录""" holding_df.loc[date, ticker] += num def execute_trade(cash, ticker, num, adj_close, date, holding_df, trans_df): """执行交易""" profit = calculate_profit(ticker, num, adj_close) cash += profit adjust_holding(holding_df, ticker, num, adj_close, date) trans_df = trans_df.append({ 'trans_date': date, 'ticker': ticker, 'num': num, 'adj_price': adj_close, 'profit': profit, 'cash': cash }, ignore_index=True) return cash, trans_df def process_trading_day(date, pivot_df, price_df, holding_df, cash, trans_df, initial_capital): """ 处理单个交易日:跨天调仓+止损判断,每天先进行资金回收 参数: date (pd.Timestamp): 当前交易日期 pivot_df (pd.DataFrame): 内幕交易数据面板,行索引是trans_date,列索引是ticker,值value为num,num的正负代表buy/sell price_df (pd.DataFrame): 每日收盘价数据,其中索引为日期,列名为股票代码 holding_df (pd.DataFrame): 当前持仓数据,其中索引为日期,列名为股票代码,值表示持有数量 cash (float): 当前现金余额 trans_df (pd.DataFrame): 交易记录数据框,用于记录每次交易详情。第一列是trans_date,第二列是ticker,第三列是num,num的正负代表buy/sell,第四列是当天该ticker的adj_price,第五列是该交易的profit(正就是赚钱了,负是cost或者亏钱),第六列是当前现金cash initial_capital (float): 初始投资本金 返回: cash (float): 更新后的现金余额 trans_df (pd.DataFrame): 更新后的交易记录数据框 """ # 止损判断,如果亏了5%或持仓超过30天,则卖出全部股票 for trans_date, ticker in holding_df.index: num = holding_df.loc[trans_date, ticker] if num > 0: current_price = price_df.loc[date, ticker] threshold_price = price_df.loc[trans_date, ticker] * 0.95 holding_duration = (date - trans_date).days if current_price < threshold_price or holding_duration > 30: cash, trans_df = execute_trade(cash, ticker, -num, current_price, date, holding_df, trans_df) # 跨天跳仓,实现部分收益条件下的卖出策略 for ticker, num in holding_df.loc[date].items(): current_price = price_df.loc[date, ticker] threshold_price = price_df.loc[trans_date, ticker] if num > 0: # 已持有的股票收益率达到2%,则卖出一半股票收回资金 #TODO:2%-4% if current_price * num - threshold_price * num * 1.02 > 0: sell_num = num / 2 cash, trans_df = execute_trade(cash, ticker, -sell_num, current_price, date, holding_df, trans_df) # 股票收益率达到4%,则出售所有股票以收回资金 elif current_price * num - threshold_price * num * 1.04 > 0: cash, trans_df = execute_trade(cash, ticker, -num, current_price, date, holding_df, trans_df) # 进入当天交易 day_pivot = pivot_df.loc[date] today_data = price_df.loc[date] if day_pivot.nunique() == 1: # 当天只有一个ticker有交易,直接处理 ticker = day_pivot.index[0] num = day_pivot[ticker] adj_close = price_df.loc[date, ticker] if num > 0: # Buy.TODO:分配70%的cash买 # 使用0.7的现金购买,不用反复记录cash,直接拨了70%现金去买 cash = 0.3 * cash buy_num = 0.7 * cash / adj_close _, trans_df = execute_trade(cash, ticker, buy_num, adj_close, date, holding_df, trans_df) else if num<0 : # Sell # TODO: 实现卖出逻辑,包括长期内幕卖出和短期内幕卖出 # holding_time() #(判断长短期) #长期内幕卖出函数:遵循内幕交易的卖出,在当前日直接卖出。 #短期内幕卖出函数:先判断该卖出交易日是对应买入的第几个卖出交易日 #如果第一个内幕交易卖出当日回报达到4%直接卖出,当日未达到,就先不卖出 #如果当前是第二个内幕交易日,如果当天收益率达到3%就卖出,未达到就不卖出 #如果当前是第三个内幕交易日or距离买入时间到第15天,全部抛出 else: # 当天num值不为零的ticker有好几个,当日资金分配 # 当天num值不为零的ticker有好几个,当日资金分配 if len(today_data[today_data != 0]) > 1: # 对当天所有有交易的stock进行购买,按照公司当天adj close*num的权重,分配0.7*cash; day_pivot = pivot_df.loc[date] trading_stocks = day_pivot.index[day_pivot.abs() > 0] trade_values = today_data.loc[trading_stocks] * day_pivot[trading_stocks].abs() weights = trade_values / trade_values.sum() allocated_funds = {stock: 0.7 * cash * weight for stock, weight in weights.items()} # 使用execute_trade()函数执行交易、更新现金余额、持仓和交易记录 for stock, amount in allocated_funds.items(): cash, trans_df = execute_trade(cash, stock, amount, today_data[stock], date, holding_df, trans_df) # 返回更新后的现金余额、持仓数据和交易记录数据框 return cash, holding_df, trans_df # 按pivot_df的trans_date列进行循环 trans_dates = pivot_df.index.unique() for date in trans_dates: cash, holding_df, trans_df = process_trading_day(date, pivot_df, price_df, holding_df, cash, trans_df, INITIAL_CAPITAL) # 最终输出结果 print("Cash at the end:", cash) print("Final Holding DF:") print(holding_df) print("Final Trans DF:") print(trans_df)