"""
计算资金曲线
"""
import pandas as pd
pd.set_option('display.max_rows', 1000) #控制台可以显示最大的行数
pd.set_option('expand_frame_repr', False)  # 当列太多时不换行
# df = pd.read_hdf('D:\work\lianghua\py\program\\bolling_signal.h5', key='all_data')
df = pd.read_hdf('D:\work\lianghua\py\data\class8\eth_bolling_signal.h5', key='all_data')

#计算涨跌幅
df['change'] = df['close'].pct_change(1) # 根据收盘价计算涨跌幅
df['daychange'] = df['close'] / df['open'] - 1  #计算今天开盘到收盘价的涨跌幅 (建仓使用,建仓以开盘价买入)
df['2days_change'] = df['open'].shift(-1) / df['close'] -1   # 从今天收盘到明天开盘的涨跌幅 (平仓时候用,第二天开盘价卖)
df.at[len(df)-1,'2days_change'] = 0 #2days涨跌幅最后一个值Nan改为0 at和loc用法相似

#选取时间段
df = df[df['candle_begin_time'] >= pd.to_datetime('2017-01-01')]
df.reset_index(inplace=True, drop=True)

#开仓平仓信号
condition1 = df['pos'] != 0
condition2 = df['pos'] != df['pos'].shift(1) #不能等于前面的pos
kaicang = condition1 & condition2

condition3 = df['pos'] != 0
condition4 = df['pos'] != df['pos'].shift(-1) #不能等于后面的pos参数
pingcang = condition3 & condition4

#对交易进行分组
df.loc[kaicang,'start_time'] = df['candle_begin_time']
df['start_time'].fillna(method='ffill',inplace=True)
df.loc[df['pos']==0,'start_time'] = pd.NaT

# ===基本参数
leverage_rate = 3  # bfx交易所最多提供3倍杠杆,leverage_rate可以在(0, 3]区间选择
init_cash = 100  # 初始资金
c_rate = 2.0 / 1000  # 手续费
min_margin_rate = 0.15  # 最低保证金比例,必须占到借来资产的15%
min_margin = init_cash * leverage_rate * min_margin_rate  # 最低保证金

#开仓时仓位
df.loc[kaicang,'position'] = init_cash*leverage_rate*(df['daychange']+1) #单独分开了算的,开仓后当天的情况

#算之后仓位变动(这里代码公式不太好理解)
group_num = len(df.groupby('start_time'))
if group_num > 1:
    t = df.groupby('start_time').apply(lambda x: x['close'] / x.iloc[0]['close'] * x.iloc[0]['position'])
    t = t.reset_index(level=[0])
    df['position'] = t['close']

# (最高价最低价/现价)*当前价格or收盘价格 = 当天资金最高最低的数值
df['posmax'] = df['position'] * df['high'] / df['close']
df['posmin'] = df['position'] * df['low'] / df['close']

# 平仓时仓位 (不太好理解)
df.loc[pingcang, 'position'] *= (1 + df.loc[pingcang, '2days_change'])

# 计算持仓利润 (最新资金-现金*杠杆)*做多做空类型
df['profit'] = (df['position'] - init_cash * leverage_rate) * df['pos']  # 持仓盈利或者损失

# 计算持仓利润最小值 (最大最小资金-现金*杠杆)*做多做空类型
df.loc[df['pos'] == 1, 'profit_min'] = (df['posmin'] - init_cash * leverage_rate) * df['pos']  # 最小持仓盈利或者损失
df.loc[df['pos'] == -1, 'profit_min'] = (df['posmax'] - init_cash * leverage_rate) * df['pos']  # 最小持仓盈利或者损失

# 计算实际资金量
df['cash'] = init_cash + df['profit']  # 实际资金 (初始资金+利润)
df['cash'] -= init_cash * leverage_rate * c_rate  # 减去建仓时的手续费
df['cash_min'] = df['cash'] - (df['profit'] - df['profit_min'])  # 实际最小资金
df.loc[pingcang, 'cash'] -= df.loc[pingcang, 'position'] * c_rate  # 减去平仓时的手续费(平仓资金减去手续费)


# ===判断是否会爆仓 NO2
_index = df[df['cash_min'] <= min_margin].index #判断最小资金是否小于最低保证金
if len(_index) > 0:
    print('有爆仓')
    df.loc[_index, '强平'] = 1
    df['强平'] = df.groupby('start_time')['强平'].fillna(method='ffill')
    df.loc[(df['强平'] == 1) & (df['强平'].shift(1) != 1), 'cash_强平'] = df['cash_min']  # 此处是有问题的
    df.loc[(df['pos'] != 0) & (df['强平'] == 1), 'cash'] = None
    df['cash'].fillna(value=df['cash_强平'], inplace=True)
    df['cash'] = df.groupby('start_time')['cash'].fillna(method='ffill')
    df.drop(['强平', 'cash_强平'], axis=1, inplace=True)  # 删除不必要的数据

#先计算资金曲线 NO1
df['equity_change'] = df['cash'].pct_change() #实际资金涨跌幅
df.loc[kaicang, 'equity_change'] = (df.loc[kaicang, 'cash'] / init_cash) - 1  # 开仓日的收益率 (开仓现金/初始资金)
df['equity_change'].fillna(value=0, inplace=True) #空值补0
#计算资金曲线,资金曲线假定从一块钱开始的(最终有多少钱)
df['equity_curve'] = (1 + df['equity_change']).cumprod()


# # ===删除不必要的数据
df.drop(['change', 'daychange', '2days_change', 'start_time', 'position', 'posmax',
         'posmin', 'profit', 'profit_min', 'cash', 'cash_min'], axis=1, inplace=True)

# =====将数据存入hdf文件中