引言:理解非会员散户在期货市场的定位
期货市场是一个高杠杆、高风险但同时蕴含高机会的金融衍生品交易领域。对于非会员散户而言,与机构投资者和交易所会员相比,我们面临着信息不对称、资金规模有限、交易成本较高等多重挑战。然而,这并不意味着散户无法在这个市场中获利。事实上,通过科学的策略、严格的纪律和有效的风险管理,散户完全可以在市场波动中找到属于自己的机会。
非会员散户通常指的是那些没有交易所会员资格、通过期货公司开户进行交易的个人投资者。与机构投资者相比,我们的优势在于决策灵活、资金调用快速、不受繁琐的合规流程限制。关键在于如何将这些优势转化为实际的交易成果,同时规避资金量小、信息获取慢等劣势。
本文将详细探讨散户如何在期货市场中制定有效的交易策略,包括如何识别市场机会、如何构建交易系统、如何进行严格的风险管理,以及如何通过技术手段提升交易效率。我们将从基础概念讲起,逐步深入到实战策略,并提供完整的代码示例来帮助理解量化交易的基本思路。
一、期货市场基础与散户面临的挑战
1.1 期货交易的基本概念
期货合约是一种标准化的协议,约定在未来某个特定日期以特定价格买入或卖出某种标的资产(如商品、股指、外汇等)。期货交易的核心特点包括:
- 杠杆效应:只需缴纳合约价值一定比例的保证金即可交易,放大收益的同时也放大风险
- 双向交易:可以做多(买入)也可以做空(卖出),无论市场涨跌都有机会
- T+0交易:当天买入的合约可以当天卖出,交易灵活
- 到期交割:合约有到期日,到期后需要进行实物交割或现金结算
1.2 非会员散户的主要挑战
作为非会员散户,在期货交易中主要面临以下挑战:
- 信息劣势:无法像机构那样获得第一手的研究报告和市场数据
- 资金规模小:难以通过资金优势影响市场,也难以承受大幅回撤
- 交易成本高:相对机构而言,手续费和滑点成本占比更高
- 心理压力大:由于资金是个人积蓄,更容易产生情绪化交易
- 技术工具少:缺乏专业的交易系统和算法支持
1.3 散户的优势与机会
尽管挑战重重,散户也有自己的独特优势:
- 决策灵活:可以快速调整策略,不需要层层审批
- 资金调用快:不需要考虑大资金进出对市场的冲击
- 专注度高:可以专注于少数几个品种,深入研究
- 无合规限制:可以尝试各种策略,不受监管约束
二、市场波动中的机会识别方法
2.1 技术分析:从价格行为中寻找机会
技术分析是散户最常用的机会识别工具,因为它只依赖公开的价格和成交量数据。以下是几种有效的技术分析方法:
2.1.1 趋势跟踪策略
趋势是期货交易的朋友。识别趋势并顺势而为是最经典的策略之一。
移动平均线交叉系统:
import pandas as pd
import numpy as np
def moving_average_crossover(df, short_window=20, long_window=50):
"""
移动平均线交叉策略
参数:
df: 包含'close'列的DataFrame
short_window: 短期均线周期
long_window: 长期均线周期
返回:
signals: 交易信号 DataFrame
"""
# 计算移动平均线
df['MA_short'] = df['close'].rolling(window=short_window).mean()
df['MA_long'] = df['close'].rolling(window=long_window).mean()
# 生成信号:短期均线上穿长期均线为买入信号,下穿为卖出信号
df['signal'] = 0
df.loc[df['MA_short'] > df['MA_long'], 'signal'] = 1 # 做多
df.loc[df['MA_short'] < df['MA_long'], 'signal'] = -1 # 做空
# 计算信号变化(金叉/死叉)
df['position'] = df['signal'].diff()
return df
# 示例数据(假设我们有某商品期货的收盘价)
data = {
'close': [100, 102, 105, 103, 101, 99, 97, 95, 93, 91, 89, 87, 85, 83, 81, 79, 77, 75, 73, 71,
69, 67, 65, 63, 61, 59, 57, 55, 53, 51, 49, 47, 45, 43, 41, 39, 37, 35, 33, 31,
29, 27, 25, 23, 21, 19, 17, 15, 13, 11, 9, 7, 5, 3, 1]
}
df = pd.DataFrame(data)
# 应用策略
result = moving_average_crossover(df, short_window=5, long_window=10)
# 查看信号变化点
entry_signals = result[result['position'] != 0]
print("交易信号点:")
print(entry_signals[['close', 'MA_short', 'MA_long', 'signal', 'position']])
这个策略的核心思想是:当短期趋势向上穿越长期趋势时,市场进入上升趋势,应该做多;反之则做空。虽然简单,但在趋势明显的市场中非常有效。
2.1.2 支撑阻力与突破策略
支撑和阻力是价格行为的重要概念。当价格突破关键阻力位时,可能意味着新的上升趋势开始;跌破支撑位则可能开启下跌趋势。
布林带突破策略:
def bollinger_bands_breakout(df, window=20, num_std=2):
"""
布林带突破策略
"""
# 计算中轨(移动平均)
df['middle_band'] = df['close'].rolling(window=window).mean()
# 计算标准差
df['std'] = df['close'].rolling(window=window).std()
# 计算上下轨
df['upper_band'] = df['middle_band'] + (df['std'] * num_std)
df['lower_band'] = df['middle_band'] - (df['std'] * num_std)
# 生成信号:价格突破上轨做多,跌破下轨做空
df['signal'] = 0
df.loc[df['close'] > df['upper_band'], 'signal'] = 1
df.loc[df['close'] < df['lower_band'], 'signal'] = -1
return df
# 使用上面的示例数据
result_bb = bollinger_bands_breakout(df, window=5, num_std=1.5)
breakout_signals = result_bb[result_bb['signal'] != 0]
print("\n布林带突破信号:")
print(breakout_signals[['close', 'middle_band', 'upper_band', 'lower_band', 'signal']])
2.1.3 形态识别策略
经典的价格形态如头肩顶/底、双顶/底、三角形整理等,都是重要的交易信号。虽然形态识别较为主观,但结合其他指标可以提高准确性。
2.2 基本面分析:从供需关系中寻找机会
对于商品期货,基本面分析尤为重要。虽然散户难以获得机构级别的数据,但仍然可以通过公开信息进行分析:
- 宏观经济数据:GDP、CPI、PPI等影响整体商品需求
- 行业供需报告:USDA(美国农业部)报告、IEA(国际能源署)报告等
- 天气因素:对农产品、能源等影响巨大
- 政策变化:关税、补贴、环保政策等
- 库存数据:EIA原油库存、CME农产品库存等
基本面分析示例(以原油期货为例):
def crude_oil_fundamental_analysis(inventory_change, production_change, demand_change):
"""
原油基本面分析简化模型
参数:
inventory_change: 库存变化(万桶)
production_change: 产量变化(万桶)
demand_change: 需求变化(万桶)
返回:
score: 基本面评分(正数看涨,负数看跌)
"""
# 库存增加利空,减少利多
inventory_score = -inventory_change * 0.5
# 产量增加利空,减少利多
production_score = -production_change * 0.3
# 需求增加利多,减少利空
demand_score = demand_change * 0.2
total_score = inventory_score + production_score + demand_score
return total_score
# 示例:某周EIA数据显示原油库存减少500万桶,产量增加20万桶,需求增加30万桶
score = crude_oil_fundamental_analysis(-500, 20, 30)
print(f"原油基本面评分:{score:.2f}")
if score > 0:
print("基本面偏向利多")
elif score < 0:
print("基本面偏向利空")
else:
print("基本面中性")
2.3 情绪分析:从市场情绪中寻找机会
市场情绪往往会导致价格偏离基本面,形成超买或超卖,为散户提供反向操作的机会。
恐慌贪婪指数(简化版):
def fear_greed_index(vix, put_call_ratio, rsi, momentum):
"""
简化的恐慌贪婪指数计算
参数:
vix: 恐慌指数(波动率指数)
put_call_ratio: 看跌看涨比率
rsi: 相对强弱指数
momentum: 动量指标
返回:
index: 0-100的指数,0表示极度恐慌,100表示极度贪婪
"""
# 标准化各指标到0-100范围
vix_score = min(100, max(0, 100 - (vix - 10) * 2)) # VIX越高越恐慌
pcr_score = min(100, max(0, 100 - put_call_ratio * 50)) # 看跌比率越高越恐慌
rsi_score = rsi # RSI已经0-100
mom_score = min(100, max(0, 50 + momentum * 10)) # 动量越高越贪婪
# 加权平均
total_score = (vix_score * 0.3 + pcr_score * 0.2 + rsi_score * 0.3 + mom_score * 0.2)
return total_score
# 示例数据
vix = 25 # 恐慌指数较高
put_call_ratio = 0.8 # 看跌略多
rsi = 35 # 超卖区域
momentum = -0.5 # 负动量
index = fear_greed_index(vix, put_call_ratio, rsi, momentum)
print(f"恐慌贪婪指数:{index:.1f}")
if index < 30:
print("市场极度恐慌,可能存在买入机会")
elif index > 70:
print("市场极度贪婪,可能存在卖出机会")
else:
print("市场情绪中性")
三、构建适合散户的交易系统
3.1 交易系统的核心要素
一个完整的交易系统应包含以下要素:
- 入场规则:明确什么条件下开仓
- 出场规则:明确什么条件下平仓(止盈和止损)
- 仓位管理:每次交易投入多少资金
- 品种选择:交易哪些期货品种
- 时间框架:在哪个时间级别上交易
3.2 多时间框架分析系统
多时间框架分析是提高胜率的有效方法。通过在大周期确定趋势,在小周期寻找入场点,可以过滤掉很多噪音。
多时间框架分析代码示例:
def multi_timeframe_analysis(df_daily, df_hourly, trend_period=50, entry_period=20):
"""
多时间框架分析系统
参数:
df_daily: 日线数据
df_hourly: 小时线数据
trend_period: 趋势判断周期
entry_period: 入场判断周期
返回:
signals: 包含多时间框架信号的DataFrame
"""
# 大周期(日线)判断趋势
df_daily['MA_trend'] = df_daily['close'].rolling(window=trend_period).mean()
df_daily['trend_direction'] = np.where(df_daily['close'] > df_daily['MA_trend'], 1, -1)
# 小周期(小时线)寻找入场点
df_hourly['MA_entry'] = df_hourly['close'].rolling(window=entry_period).mean()
df_hourly['entry_signal'] = np.where(df_hourly['close'] > df_hourly['MA_entry'], 1, -1)
# 对齐时间(简化处理,实际需要更复杂的时间对齐)
# 这里假设我们只取小时线最后一个数据点
current_trend = df_daily['trend_direction'].iloc[-1]
current_entry = df_hourly['entry_signal'].iloc[-1]
# 最终信号:只有当大趋势和小周期入场信号一致时才交易
final_signal = 0
if current_trend == 1 and current_entry == 1:
final_signal = 1 # 做多
elif current_trend == -1 and current_entry == -1:
final_signal = -1 # 做空
return final_signal
# 示例数据(简化)
daily_data = {'close': [100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110]}
hourly_data = {'close': [108, 108.5, 109, 109.5, 110, 110.5, 111, 111.5, 112, 112.5, 113]}
df_daily = pd.DataFrame(daily_data)
df_hourly = pd.DataFrame(hourly_data)
signal = multi_timeframe_analysis(df_daily, df_hourly)
print(f"多时间框架分析信号:{signal}")
if signal == 1:
print("建议做多")
elif signal == -1:
print("建议做空")
else:
print("建议观望")
3.3 交易日志与复盘系统
交易日志是散户提升交易水平的关键工具。通过记录每一笔交易的细节,可以发现自己的优势和劣势。
交易日志系统代码示例:
import json
from datetime import datetime
class TradingJournal:
def __init__(self):
self.trades = []
def add_trade(self, symbol, direction, entry_price, exit_price,
entry_time, exit_time, position_size, stop_loss, take_profit,
reason, result, notes=""):
"""
添加交易记录
"""
trade = {
'symbol': symbol,
'direction': direction, # 'long' or 'short'
'entry_price': entry_price,
'exit_price': exit_price,
'entry_time': entry_time,
'exit_time': exit_time,
'position_size': position_size,
'stop_loss': stop_loss,
'take_profit': take_profit,
'reason': reason, # 交易理由
'result': result, # 'win', 'loss', 'breakeven'
'profit_loss': (exit_price - entry_price) * position_size if direction == 'long'
else (entry_price - exit_price) * position_size,
'notes': notes,
'timestamp': datetime.now().isoformat()
}
self.trades.append(trade)
def analyze_performance(self):
"""
分析交易表现
"""
if not self.trades:
return "暂无交易记录"
total_trades = len(self.trades)
wins = len([t for t in self.trades if t['result'] == 'win'])
losses = len([t for t in self.trades if t['result'] == 'loss'])
win_rate = wins / total_trades * 100
total_profit = sum(t['profit_loss'] for t in self.trades if t['result'] == 'win')
total_loss = sum(t['profit_loss'] for t in self.trades if t['result'] == 'loss')
profit_factor = abs(total_profit / total_loss) if total_loss != 0 else float('inf')
analysis = {
'总交易数': total_trades,
'盈利交易': wins,
'亏损交易': losses,
'胜率(%)': round(win_rate, 2),
'总盈利': round(total_profit, 2),
'总亏损': round(total_loss, 2),
'净利润': round(total_profit + total_loss, 2),
'盈亏比': round(profit_factor, 2)
}
return analysis
def save_to_file(self, filename):
"""保存交易记录到文件"""
with open(filename, 'w') as f:
json.dump(self.trades, f, indent=2)
def load_from_file(self, filename):
"""从文件加载交易记录"""
with open(filename, 'r') as f:
self.trades = json.load(f)
# 使用示例
journal = TradingJournal()
# 模拟添加几笔交易
journal.add_trade(
symbol='RB2405',
direction='long',
entry_price=3800,
exit_price=3900,
entry_time='2024-01-15 09:00:00',
exit_time='2024-01-16 14:00:00',
position_size=10,
stop_loss=3750,
take_profit=3950,
reason='突破日线阻力位,多头趋势确认',
result='win',
notes='成交量配合良好'
)
journal.add_trade(
symbol='SC2403',
direction='short',
entry_price=550,
exit_price=560,
entry_time='2024-01-20 10:00:00',
exit_time='2024-01-20 15:00:00',
position_size=5,
stop_loss=555,
take_profit=540,
reason='EIA库存意外增加,尝试做空',
result='loss',
notes='止损被扫,随后价格反弹'
)
# 分析表现
performance = journal.analyze_performance()
print("\n交易表现分析:")
for key, value in performance.items():
print(f"{key}: {value}")
# 保存记录
journal.save_to_file('trading_journal.json')
四、风险管理:散户生存的根本
4.1 仓位管理:控制单笔风险
凯利公式(简化版): 凯利公式可以帮助确定最优仓位大小:
f = (p * b - q) / b
其中:
- f = 应投入的资金比例
- p = 胜率
- q = 败率(1-p)
- b = 盈亏比(平均盈利/平均亏损)
代码实现:
def kelly_criterion(win_rate, win_loss_ratio):
"""
计算凯利仓位比例
参数:
win_rate: 胜率(0-1)
win_loss_ratio: 盈亏比(平均盈利/平均亏损)
返回:
kelly_fraction: 凯利比例(建议只使用50%的凯利仓位)
"""
if win_rate <= 0 or win_loss_ratio <= 0:
return 0
q = 1 - win_rate
kelly = (win_rate * win_loss_ratio - q) / win_loss_ratio
# 实际应用中通常只使用半凯利或1/3凯利以降低风险
conservative_kelly = kelly * 0.5
return max(0, conservative_kelly)
# 示例:假设胜率40%,盈亏比2.5
win_rate = 0.4
win_loss_ratio = 2.5
kelly = kelly_criterion(win_rate, win_loss_ratio)
print(f"凯利仓位比例:{kelly:.2%}")
print(f"如果总资金10万元,建议仓位:{100000 * kelly:.0f}元")
固定风险仓位法(更适合散户):
def fixed_risk_position(account_balance, risk_per_trade=0.01, stop_loss_pips=50, point_value=10):
"""
固定风险仓位计算
参数:
account_balance: 账户余额
risk_per_trade: 单笔风险比例(如1%)
stop_loss_pips: 止损点数
point_value: 每点价值(元)
返回:
position_size: 合约数量
"""
# 单笔最大亏损金额
max_loss = account_balance * risk_per_trade
# 每手合约的亏损金额
loss_per_contract = stop_loss_pips * point_value
# 计算可开仓手数
position_size = max_loss / loss_per_contract
return int(position_size)
# 示例:10万资金,1%风险,止损50点,每点10元
balance = 100000
position = fixed_risk_position(balance, risk_per_trade=0.01, stop_loss_pips=50, point_value=10)
print(f"固定风险仓位:{position}手")
4.2 止损策略:截断亏损
4.2.1 技术止损
- 固定点数止损:入场后固定点数止损
- 移动平均线止损:价格跌破某条均线止损
- ATR止损:基于波动率的止损
- 支撑阻力止损:跌破关键支撑位止损
ATR止损代码:
def atr_stop_loss(df, atr_period=14, multiplier=2):
"""
ATR止损计算
"""
# 计算ATR(平均真实波幅)
high_low = df['high'] - df['low']
high_close = np.abs(df['high'] - df['close'].shift())
low_close = np.abs(df['low'] - df['close'].shift())
ranges = pd.concat([high_low, high_close, low_close], axis=1)
true_range = np.max(ranges, axis=1)
atr = true_range.rolling(window=atr_period).mean()
# 计算止损位
df['stop_loss_long'] = df['close'] - multiplier * atr # 多头止损
df['stop_loss_short'] = df['close'] + multiplier * atr # 空头止损
return df[['stop_loss_long', 'stop_loss_short']]
# 示例数据
data = {
'high': [102, 103, 104, 105, 106, 107, 108, 109, 110, 111],
'low': [100, 101, 102, 103, 104, 105, 106, 107, 108, 109],
'close': [101, 102, 103, 104, 105, 106, 107, 108, 109, 110]
}
df = pd.DataFrame(data)
atr_sl = atr_stop_loss(df, atr_period=5, multiplier=2)
print("\nATR止损位:")
print(atr_sl.tail(3))
4.2.2 资金止损
根据账户资金比例设置止损,如每笔交易亏损不超过总资金的2%。
4.2.3 时间止损
如果价格在预定时间内没有按预期移动,即使没到止损位也平仓。
4.3 止盈策略:让利润奔跑
4.3.1 固定比例止盈
达到预定盈利目标后平仓。
4.3.2 移动止损(Trailing Stop)
随着盈利增加,止损位也相应上移,保护已有利润。
移动止损代码:
def trailing_stop(df, initial_stop, trail_amount, direction='long'):
"""
移动止损实现
参数:
df: 价格数据
initial_stop: 初始止损位
trail_amount: 回撤幅度
direction: 'long' or 'short'
返回:
stop_level: 当前止损位
"""
if direction == 'long':
# 多头移动止损:最高价 - 回撤幅度
highest = df['high'].expanding().max()
stop_level = highest - trail_amount
# 确保止损位不会下降
stop_level = stop_level.cummax()
else:
# 空头移动止损:最低价 + 回撤幅度
lowest = df['low'].expanding().min()
stop_level = lowest + trail_amount
# 确保止损位不会上升
stop_level = stop_level.cummin()
return stop_level
# 示例
data = {
'high': [100, 101, 102, 103, 102, 101, 100, 99, 98, 97],
'low': [99, 100, 101, 102, 101, 100, 99, 98, 97, 96]
}
df = pd.DataFrame(data)
trailing_sl = trailing_stop(df, initial_stop=98, trail_amount=2, direction='long')
print("\n移动止损位:")
print(trailing_sl)
4.4 多品种分散与相关性管理
品种相关性分析:
import seaborn as sns
import matplotlib.pyplot as plt
def correlation_analysis(price_data):
"""
计算品种相关性矩阵
price_data: 包含多个品种价格的DataFrame
"""
returns = price_data.pct_change().dropna()
corr_matrix = returns.corr()
return corr_matrix
# 示例:假设有三个品种的日收益率
data = {
'RB': [0.01, 0.02, -0.01, 0.03, -0.02, 0.01, 0.02, -0.01, 0.03, -0.02],
'HC': [0.015, 0.018, -0.008, 0.025, -0.015, 0.012, 0.018, -0.009, 0.028, -0.018],
'I': [0.02, 0.03, -0.02, 0.04, -0.03, 0.02, 0.03, -0.02, 0.04, -0.03]
}
df_prices = pd.DataFrame(data)
corr = correlation_analysis(df_prices)
print("\n品种相关性矩阵:")
print(corr)
# 避免同时交易高度正相关(>0.8)或高度负相关(<-0.8)的品种
五、散户实战策略详解
5.1 日内波段交易策略
适合有时间盯盘的散户,利用日内波动获利。
策略逻辑:
- 使用15分钟或30分钟图确定日内趋势
- 在5分钟图上寻找入场点
- 设置1:2的盈亏比
- 当日平仓,不隔夜
完整代码实现:
def intraday_swing_strategy(df_30min, df_5min, atr_period=14):
"""
日内波段交易策略
"""
# 30分钟图确定趋势
df_30min['MA30'] = df_30min['close'].rolling(window=30).mean()
df_30min['trend'] = np.where(df_30min['close'] > df_30min['MA30'], 1, -1)
# 5分钟图寻找入场
df_5min['MA5'] = df_5min['close'].rolling(window=5).mean()
df_5min['MA20'] = df_5min['close'].rolling(window=20).mean()
# 计算ATR用于止损止盈
high_low = df_5min['high'] - df_5min['low']
high_close = np.abs(df_5min['high'] - df_5min['close'].shift())
low_close = np.abs(df_5min['low'] - df_5min['close'].shift())
ranges = pd.concat([high_low, high_close, low_close], axis=1)
true_range = np.max(ranges, axis=1)
atr = true_range.rolling(window=atr_period).mean()
# 生成信号
df_5min['signal'] = 0
# 多头信号:30分钟趋势向上,5分钟金叉
long_condition = (df_30min['trend'].iloc[-1] == 1) & \
(df_5min['MA5'] > df_5min['MA20'])
# 空头信号:30分钟趋势向下,5分钟死叉
short_condition = (df_30min['trend'].iloc[-1] == -1) & \
(df_5min['MA5'] < df_5min['MA20'])
df_5min.loc[long_condition, 'signal'] = 1
df_5min.loc[short_condition, 'signal'] = -1
# 计算止损止盈位(最后一根K线)
last_close = df_5min['close'].iloc[-1]
last_atr = atr.iloc[-1]
stop_loss = last_close - 1.5 * last_atr if long_condition else last_close + 1.5 * last_atr
take_profit = last_close + 3 * last_atr if long_condition else last_close - 3 * last_atr
return {
'signal': df_5min['signal'].iloc[-1],
'entry_price': last_close,
'stop_loss': stop_loss,
'take_profit': take_profit,
'atr': last_atr
}
# 模拟数据(30分钟和5分钟)
import pandas as pd
import numpy as np
# 生成模拟价格数据
np.random.seed(42)
n_30min = 100
n_5min = n_30min * 6 # 30分钟数据对应6倍的5分钟数据
# 30分钟数据
df_30min = pd.DataFrame({
'close': 100 + np.cumsum(np.random.randn(n_30min) * 0.5),
'high': 100 + np.cumsum(np.random.randn(n_30min) * 0.5) + 0.5,
'low': 100 + np.cumsum(np.random.randn(n_30min) * 0.5) - 0.5
})
# 5分钟数据(更细粒度)
df_5min = pd.DataFrame({
'close': 100 + np.cumsum(np.random.randn(n_5min) * 0.2),
'high': 100 + np.cumsum(np.random.randn(n_5min) * 0.2) + 0.2,
'low': 100 + np.cumsum(np.random.randn(n_5min) * 0.2) - 0.2
})
# 运行策略
result = intraday_swing_strategy(df_30min, df_5min)
print("\n日内波段策略信号:")
print(result)
5.2 隔夜趋势策略
适合无法盯盘的上班族,利用日线级别的趋势。
策略逻辑:
- 使用日线图,20日均线判断趋势
- 收盘价突破20日均线买入,跌破卖出
- 每日收盘后评估信号,次日开盘执行
- 设置2%的固定止损
代码实现:
def overnight_trend_strategy(df_daily, ma_period=20):
"""
隔夜趋势策略
"""
# 计算移动平均线
df_daily['MA'] = df_daily['close'].rolling(window=ma_period).mean()
# 计算信号(收盘价对比均线)
df_daily['signal'] = 0
df_daily.loc[df_daily['close'] > df_daily['MA'], 'signal'] = 1
df_daily.loc[df_daily['close'] < df_daily['MA'], 'signal'] = -1
# 信号变化(金叉/死叉)
df_daily['position_change'] = df_daily['signal'].diff()
# 获取最新信号
current_signal = df_daily['signal'].iloc[-1]
last_signal = df_daily['signal'].iloc[-2]
# 今日是否应该调整仓位
should_adjust = current_signal != last_signal
result = {
'current_position': current_signal, # 1:持多仓,-1:持空仓,0:空仓
'should_adjust': should_adjust,
'adjust_direction': current_signal if should_adjust else 0,
'stop_loss_level': df_daily['close'].iloc[-1] * 0.98 if current_signal == 1
else df_daily['close'].iloc[-1] * 1.02 if current_signal == -1
else None
}
return result
# 示例数据
daily_data = pd.DataFrame({
'close': [100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101]
})
overnight_result = overnight_trend_strategy(daily_data)
print("\n隔夜趋势策略结果:")
print(overnight_result)
5.3 套利策略(适合有编程能力的散户)
跨期套利:同一品种不同月份合约的价差交易。
跨品种套利:相关品种间的价差交易(如螺纹钢与铁矿石)。
代码示例(跨期套利):
def calendar_spread_strategy(df_near, df_far, threshold=1.0):
"""
跨期套利策略
参数:
df_near: 近月合约数据
df_far: 远月合约数据
threshold: 价差偏离阈值(倍数)
返回:
signal: 交易信号
"""
# 计算价差
spread = df_far['close'] - df_near['close']
# 计算价差的均值和标准差
spread_mean = spread.rolling(window=20).mean()
spread_std = spread.rolling(window=20).std()
# 当前价差
current_spread = spread.iloc[-1]
current_mean = spread_mean.iloc[-1]
current_std = spread_std.iloc[-1]
# 判断是否偏离
if current_std > 0:
z_score = (current_spread - current_mean) / current_std
# 信号:Z-score > 2做空价差(空远月,多近月)
# Z-score < -2做多价差(多远月,空近月)
if z_score > threshold:
signal = -1 # 做空价差
elif z_score < -threshold:
signal = 1 # 做多价差
else:
signal = 0 # 观望
else:
signal = 0
return {
'signal': signal,
'spread': current_spread,
'z_score': z_score if current_std > 0 else 0,
'action': '空远月多近月' if signal == -1
else '多远月空近月' if signal == 1
else '观望'
}
# 示例数据
df_near = pd.DataFrame({'close': [100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110]})
df_far = pd.DataFrame({'close': [102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112]})
spread_result = calendar_spread_strategy(df_near, df_far)
print("\n跨期套利策略:")
print(spread_result)
六、心理控制与交易纪律
6.1 常见心理陷阱
- 恐惧与贪婪:该止损时不止损,该止盈时不止盈
- 报复性交易:亏损后急于翻本,加大仓位
- 过度交易:频繁操作,增加交易成本
- 锚定效应:执着于买入成本,忽视市场变化
- 确认偏误:只关注支持自己观点的信息
6.2 建立交易纪律
交易纪律清单:
- 每笔交易前写明交易理由和计划
- 严格执行预设的止损止盈
- 单笔亏损不超过总资金的2%
- 每日最大亏损不超过总资金的5%
- 连续亏损3次后暂停交易,复盘原因
- 每周/每月进行交易复盘
纪律检查代码:
class DisciplineChecker:
def __init__(self, total_capital, max_daily_loss=0.05, max_per_trade=0.02):
self.total_capital = total_capital
self.max_daily_loss = max_daily_loss
self.max_per_trade = max_per_trade
self.daily_loss = 0
self.consecutive_losses = 0
def check_trade(self, trade_size, expected_loss, reason):
"""
检查交易是否符合纪律
"""
issues = []
# 检查单笔风险
if expected_loss > self.total_capital * self.max_per_trade:
issues.append(f"单笔风险过高:{expected_loss} > {self.total_capital * self.max_per_trade}")
# 检查当日剩余风险
remaining_risk = self.total_capital * self.max_daily_loss - self.daily_loss
if expected_loss > remaining_risk:
issues.append(f"超过当日剩余风险:{expected_loss} > {remaining_risk}")
# 检查连续亏损
if self.consecutive_losses >= 3:
issues.append("已连续亏损3次,建议暂停交易")
# 检查交易理由
if not reason or len(reason.strip()) < 10:
issues.append("交易理由不充分")
return {
'can_trade': len(issues) == 0,
'issues': issues,
'warning': len(issues) > 0
}
def update_after_trade(self, profit_loss):
"""交易后更新状态"""
self.daily_loss += min(0, profit_loss)
if profit_loss < 0:
self.consecutive_losses += 1
else:
self.consecutive_losses = 0
def reset_daily(self):
"""每日重置"""
self.daily_loss = 0
self.consecutive_losses = 0
# 使用示例
checker = DisciplineChecker(total_capital=100000)
# 检查一笔交易
trade_check = checker.check_trade(
trade_size=10000,
expected_loss=2000,
reason="突破日线阻力位,成交量放大,MACD金叉"
)
print("\n纪律检查结果:")
print(trade_check)
# 模拟交易后
checker.update_after_trade(-2000)
print(f"更新后连续亏损次数:{checker.consecutive_losses}")
6.3 交易复盘模板
复盘要点:
- 交易是否符合系统规则?
- 止损止盈设置是否合理?
- 心理状态如何?
- 有没有受情绪影响?
- 如果重来,会怎么做?
七、技术工具与资源
7.1 免费数据源
- Tushare:国内期货数据(Python库)
- AkShare:免费金融数据接口
- 新浪财经:实时行情
- 文华财经:行情软件(有免费版)
7.2 交易软件
- 无限易:免费量化交易软件
- Vn.py:开源交易框架
- Backtrader:回测框架
7.3 学习资源
- 书籍:《期货市场技术分析》、《通向财务自由之路》
- 网站:Investopedia、Babypips
- 社区:交易论坛、量化社区
八、实战案例:完整交易流程演示
8.1 案例背景
假设我们有10万元资金,计划交易螺纹钢期货(RB2405)。
8.2 完整流程代码
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
class FuturesTradingSystem:
def __init__(self, capital, symbol, point_value=10):
self.capital = capital
self.symbol = symbol
self.point_value = point_value # 每点价值(元)
self.position = 0 # 持仓方向:1多仓,-1空仓,0空仓
self.entry_price = 0
self.stop_loss = 0
self.take_profit = 0
self.trades = []
self.balance = capital
def calculate_position_size(self, stop_loss_pips, risk_per_trade=0.01):
"""计算仓位"""
max_loss = self.capital * risk_per_trade
loss_per_contract = stop_loss_pips * self.point_value
return int(max_loss / loss_per_contract)
def generate_signal(self, df, strategy='trend'):
"""生成交易信号"""
if strategy == 'trend':
# 趋势跟踪:20日均线
df['MA20'] = df['close'].rolling(window=20).mean()
current_price = df['close'].iloc[-1]
ma20 = df['MA20'].iloc[-1]
if current_price > ma20 and self.position <= 0:
return 1 # 做多信号
elif current_price < ma20 and self.position >= 0:
return -1 # 做空信号
else:
return 0 # 无信号
return 0
def execute_trade(self, signal, df, atr_period=14):
"""执行交易"""
current_price = df['close'].iloc[-1]
# 计算ATR用于止损
high_low = df['high'] - df['low']
high_close = np.abs(df['high'] - df['close'].shift())
low_close = np.abs(df['low'] - df['close'].shift())
ranges = pd.concat([high_low, high_close, low_close], axis=1)
true_range = np.max(ranges, axis=1)
atr = true_range.rolling(window=atr_period).mean().iloc[-1]
if signal == 1: # 开多仓或平空仓
if self.position <= 0:
# 平空仓(如果有)
if self.position == -1:
self.close_position(current_price, '平空开多')
# 开多仓
stop_loss_pips = int(1.5 * atr)
position_size = self.calculate_position_size(stop_loss_pips)
if position_size > 0:
self.position = 1
self.entry_price = current_price
self.stop_loss = current_price - stop_loss_pips * 0.1 # 假设每点0.1元变动
self.take_profit = current_price + 2 * stop_loss_pips * 0.1
trade = {
'time': datetime.now(),
'action': '开多',
'price': current_price,
'size': position_size,
'stop_loss': self.stop_loss,
'take_profit': self.take_profit,
'reason': '趋势突破'
}
self.trades.append(trade)
print(f"开多仓:价格{current_price},手数{position_size},止损{self.stop_loss},止盈{self.take_profit}")
elif signal == -1: # 开空仓或平多仓
if self.position >= 0:
# 平多仓(如果有)
if self.position == 1:
self.close_position(current_price, '平多开空')
# 开空仓
stop_loss_pips = int(1.5 * atr)
position_size = self.calculate_position_size(stop_loss_pips)
if position_size > 0:
self.position = -1
self.entry_price = current_price
self.stop_loss = current_price + stop_loss_pips * 0.1
self.take_profit = current_price - 2 * stop_loss_pips * 0.1
trade = {
'time': datetime.now(),
'action': '开空',
'price': current_price,
'size': position_size,
'stop_loss': self.stop_loss,
'take_profit': self.take_profit,
'reason': '趋势跌破'
}
self.trades.append(trade)
print(f"开空仓:价格{current_price},手数{position_size},止损{self.stop_loss},止盈{self.take_profit}")
def check_exit(self, df):
"""检查是否需要平仓"""
if self.position == 0:
return False
current_price = df['close'].iloc[-1]
# 止损检查
if self.position == 1 and current_price <= self.stop_loss:
self.close_position(current_price, '止损平多')
return True
elif self.position == -1 and current_price >= self.stop_loss:
self.close_position(current_price, '止损平空')
return True
# 止盈检查
if self.position == 1 and current_price >= self.take_profit:
self.close_position(current_price, '止盈平多')
return True
elif self.position == -1 and current_price <= self.take_profit:
self.close_position(current_price, '止盈平空')
return True
return False
def close_position(self, price, reason):
"""平仓"""
if self.position == 1:
profit = (price - self.entry_price) * self.position_size * self.point_value
elif self.position == -1:
profit = (self.entry_price - price) * self.position_size * self.point_value
else:
profit = 0
self.balance += profit
trade = {
'time': datetime.now(),
'action': reason,
'price': price,
'profit': profit,
'balance': self.balance
}
self.trades.append(trade)
print(f"{reason}:价格{price},盈亏{profit:.2f},账户余额{self.balance:.2f}")
# 重置持仓
self.position = 0
self.entry_price = 0
self.stop_loss = 0
self.take_profit = 0
def run_strategy(self, df, start_date, end_date):
"""运行策略"""
df_period = df[(df.index >= start_date) & (df.index <= end_date)]
for i in range(20, len(df_period)):
df_slice = df_period.iloc[:i+1]
# 检查是否需要平仓
if self.check_exit(df_slice):
continue
# 生成信号
signal = self.generate_signal(df_slice)
# 执行交易
if signal != 0:
self.execute_trade(signal, df_slice)
return self.trades, self.balance
# 模拟数据生成
def generate_mock_data(days=100):
"""生成模拟期货数据"""
dates = pd.date_range(start='2024-01-01', periods=days, freq='D')
np.random.seed(42)
# 生成带趋势的随机游走
trend = np.linspace(3800, 4200, days) # 向上趋势
noise = np.random.randn(days) * 30 # 随机波动
close = trend + noise
high = close + np.random.rand(days) * 20
low = close - np.random.rand(days) * 20
df = pd.DataFrame({
'date': dates,
'open': close - np.random.rand(days) * 10,
'high': high,
'low': low,
'close': close,
'volume': np.random.randint(10000, 50000, days)
})
df.set_index('date', inplace=True)
return df
# 运行完整案例
print("="*60)
print("完整交易案例:螺纹钢期货趋势跟踪策略")
print("="*60)
# 生成数据
data = generate_mock_data(100)
# 初始化交易系统
system = FuturesTradingSystem(capital=100000, symbol='RB2405', point_value=10)
# 运行策略(模拟2024年1月15日到2月15日)
trades, final_balance = system.run_strategy(
data,
start_date='2024-01-15',
end_date='2024-02-15'
)
print(f"\n最终账户余额:{final_balance:.2f}")
print(f"总交易次数:{len([t for t in trades if t['action'] in ['开多', '开空']])}")
print(f"总盈亏:{final_balance - 100000:.2f}")
# 交易记录分析
print("\n交易记录:")
for trade in trades:
if trade['action'] in ['开多', '开空', '止损平多', '止损平空', '止盈平多', '止盈平空', '平多开多', '平空开空', '平多开空', '平空开多']:
print(f"{trade['time'].strftime('%Y-%m-%d %H:%M')} | {trade['action']} | 价格: {trade['price']:.2f} | ", end="")
if 'profit' in trade:
print(f"盈亏: {trade['profit']:.2f} | 余额: {trade['balance']:.2f}")
elif 'size' in trade:
print(f"手数: {trade['size']} | 止损: {trade['stop_loss']:.2f} | 止盈: {trade['take_profit']:.2f}")
else:
print()
九、总结与建议
9.1 核心要点回顾
- 顺势而为:趋势是散户最好的朋友,不要逆势操作
- 严格止损:每次交易都要预设止损,这是生存的根本
- 控制仓位:永远不要满仓,单笔风险控制在1-2%
- 保持纪律:交易系统+纪律=长期盈利
- 持续学习:市场在变,策略也需要不断优化
9.2 给散户的特别建议
- 从模拟开始:至少3个月模拟交易,验证策略有效性
- 专注少数品种:深入研究1-2个品种,比广撒网更有效
- 记录每笔交易:这是最好的老师
- 控制情绪:交易是马拉松,不是百米冲刺
- 接受亏损:亏损是交易成本的一部分,关键是如何控制
9.3 常见问题解答
Q: 多少资金可以开始期货交易? A: 建议至少5万元以上,因为要保证单笔风险可控。太少的话,止损空间和仓位管理都会受限。
Q: 应该全职做交易吗? A: 不建议。在稳定盈利前,保留本职工作。交易需要时间和经验的积累。
Q: 如何选择期货公司? A: 选择评级高、手续费合理、系统稳定的公司。手续费可以谈,尽量降低交易成本。
Q: 量化交易适合散户吗? A: 适合。即使简单的量化策略也能帮助克服情绪,保持纪律。可以从Python基础学起。
9.4 最后的忠告
期货市场不是赌场,而是需要专业技能的竞技场。作为非会员散户,我们没有信息优势,没有资金优势,但我们有灵活、专注和纪律。通过建立科学的交易系统,严格执行风险管理,持续学习和复盘,散户完全可以在市场中获得稳定的收益。
记住:生存第一,盈利第二。只有在市场中活下来,才有机会实现财务目标。祝各位交易顺利!
免责声明:本文仅供学习参考,不构成投资建议。期货交易风险巨大,可能导致本金全部损失,请谨慎投资。
