def get_butterfly_panel_plot(**kwargs):

    report_date = kwargs['report_date']
    id = kwargs['id']

    bf_output = fb.generate_futures_butterfly_sheet_4date(date_to=report_date)
    butterflies = bf_output['butterflies']

    contract_list = [butterflies['ticker1'][id], butterflies['ticker2'][id], butterflies['ticker3'][id]]
    tr_dte_list = [butterflies['trDte1'][id], butterflies['trDte2'][id], butterflies['trDte3'][id]]

    if 'aggregation_method' in kwargs.keys():
        aggregation_method = kwargs['aggregation_method']
    else:
        aggregation_method = butterflies['agg'][id]

    if 'contracts_back' in kwargs.keys():
        contracts_back = kwargs['contracts_back']
    else:
        contracts_back = butterflies['cBack'][id]

    post_report_date = exp.doubledate_shift_bus_days(double_date=report_date,shift_in_days=-20)

    bf_signals_output = fs.get_futures_butterfly_signals(ticker_list=contract_list,
                                          tr_dte_list=tr_dte_list,
                                          aggregation_method=aggregation_method,
                                          contracts_back=contracts_back,
                                          date_to=post_report_date,
                                          contract_multiplier=butterflies['multiplier'][id],
                                          use_last_as_current=True)

    aligned_data = bf_signals_output['aligned_output']['aligned_data']

    new_index = list(range(len(aligned_data.index)))
    contract_change_indx = (aligned_data['c1']['ticker_year']-aligned_data['c1']['ticker_year'].shift(1)!=0).values
    front_contract_year = aligned_data['c1']['ticker_year'] % 10
    contract_change_indx[0] = False

    report_datetime = cu.convert_doubledate_2datetime(report_date)

    x_index = [x for x in new_index if aligned_data['settle_date'][x] == report_datetime][0]

    x_tick_locations = [x for x in new_index if contract_change_indx[x]]
    x_tick_locations.append(x_index)

    x_tick_values = [cmi.letter_month_string[aligned_data['c1']['ticker_month'].values[x]-1]+
                     str(front_contract_year.values[x]) for x in new_index if contract_change_indx[x]]
    x_tick_values.append('X')

    plt.figure(figsize=(16, 7))
    plt.plot(aligned_data['residuals'])
    plt.xticks(x_tick_locations,x_tick_values)
    plt.grid()
    plt.title('Contracts: ' + str(contract_list) + ', weight2: ' + str(bf_signals_output['second_spread_weight_1'].round(2)))
    plt.show()

    return bf_signals_output
def get_butterfly_panel_plot(**kwargs):

    report_date = kwargs['report_date']
    id = kwargs['id']

    bf_output = fb.generate_futures_butterfly_sheet_4date(date_to=report_date)
    butterflies = bf_output['butterflies']

    contract_list = [butterflies['ticker1'][id], butterflies['ticker2'][id], butterflies['ticker3'][id]]
    tr_dte_list = [butterflies['trDte1'][id], butterflies['trDte2'][id], butterflies['trDte3'][id]]

    if 'aggregation_method' in kwargs.keys():
        aggregation_method = kwargs['aggregation_method']
    else:
        aggregation_method = butterflies['agg'][id]

    if 'contracts_back' in kwargs.keys():
        contracts_back = kwargs['contracts_back']
    else:
        contracts_back = butterflies['cBack'][id]

    post_report_date = exp.doubledate_shift_bus_days(double_date=report_date,shift_in_days=-20)

    bf_signals_output = fs.get_futures_butterfly_signals(ticker_list=contract_list,
                                          tr_dte_list=tr_dte_list,
                                          aggregation_method=aggregation_method,
                                          contracts_back=contracts_back,
                                          date_to=post_report_date,
                                          contract_multiplier=butterflies['multiplier'][id],
                                          use_last_as_current=True)

    aligned_data = bf_signals_output['aligned_output']['aligned_data']

    new_index = list(range(len(aligned_data.index)))
    contract_change_indx = (aligned_data['c1']['ticker_year']-aligned_data['c1']['ticker_year'].shift(1)!=0).values
    front_contract_year = aligned_data['c1']['ticker_year'] % 10
    contract_change_indx[0] = False

    report_datetime = cu.convert_doubledate_2datetime(report_date)

    x_index = [x for x in new_index if aligned_data['settle_date'][x] == report_datetime][0]

    x_tick_locations = [x for x in new_index if contract_change_indx[x]]
    x_tick_locations.append(x_index)

    x_tick_values = [cmi.letter_month_string[aligned_data['c1']['ticker_month'].values[x]-1]+
                     str(front_contract_year.values[x]) for x in new_index if contract_change_indx[x]]
    x_tick_values.append('X')

    plt.figure(figsize=(16, 7))
    plt.plot(aligned_data['residuals'])
    plt.xticks(x_tick_locations,x_tick_values)
    plt.grid()
    plt.title('Contracts: ' + str(contract_list) + ', weight2: ' + str(bf_signals_output['second_spread_weight_1'].round(2)))
    plt.show()

    return bf_signals_output
def get_butterfly_scatter_plot(**kwargs):

    report_date = kwargs['report_date']
    id = kwargs['id']

    bf_output = fb.generate_futures_butterfly_sheet_4date(date_to=report_date)
    butterflies = bf_output['butterflies']

    contract_list = [butterflies['ticker1'][id],butterflies['ticker2'][id],butterflies['ticker3'][id]]
    tr_dte_list = [butterflies['trDte1'][id],butterflies['trDte2'][id],butterflies['trDte3'][id]]

    if 'aggregation_method' in kwargs.keys():
        aggregation_method = kwargs['aggregation_method']
    else:
        aggregation_method = butterflies['agg'][id]

    if 'contracts_back' in kwargs.keys():
        contracts_back = kwargs['contracts_back']
    else:
        contracts_back = butterflies['cBack'][id]

    bf_signals_output = fs.get_futures_butterfly_signals(ticker_list=contract_list,
                                          tr_dte_list=tr_dte_list,
                                          aggregation_method=aggregation_method,
                                          contracts_back=contracts_back,
                                          date_to=report_date,
                                          contract_multiplier=butterflies['multiplier'][id])

    last5_years_indx = bf_signals_output['last5_years_indx']

    yield1 = bf_signals_output['yield1']
    yield2 = bf_signals_output['yield2']

    yield1_current = bf_signals_output['yield1_current']
    yield2_current = bf_signals_output['yield2_current']

    yield1_last5_years = yield1[last5_years_indx]
    yield2_last5_years = yield2[last5_years_indx]

    plt.figure(figsize=(16,7))
    plt.scatter(yield2, yield1, color='b')
    plt.scatter(yield2_last5_years,yield1_last5_years, color='k')
    plt.scatter(yield2_current, yield1_current, color='r')
    plt.legend(['old', 'recent', 'last'], frameon=False)
    plt.grid()
    plt.show()

    return bf_signals_output
def get_butterfly_scatter_plot(**kwargs):

    report_date = kwargs['report_date']
    id = kwargs['id']

    bf_output = fb.generate_futures_butterfly_sheet_4date(date_to=report_date)
    butterflies = bf_output['butterflies']

    contract_list = [butterflies['ticker1'][id],butterflies['ticker2'][id],butterflies['ticker3'][id]]
    tr_dte_list = [butterflies['trDte1'][id],butterflies['trDte2'][id],butterflies['trDte3'][id]]

    if 'aggregation_method' in kwargs.keys():
        aggregation_method = kwargs['aggregation_method']
    else:
        aggregation_method = butterflies['agg'][id]

    if 'contracts_back' in kwargs.keys():
        contracts_back = kwargs['contracts_back']
    else:
        contracts_back = butterflies['cBack'][id]

    bf_signals_output = fs.get_futures_butterfly_signals(ticker_list=contract_list,
                                          tr_dte_list=tr_dte_list,
                                          aggregation_method=aggregation_method,
                                          contracts_back=contracts_back,
                                          date_to=report_date,
                                          contract_multiplier=butterflies['multiplier'][id])

    last5_years_indx = bf_signals_output['last5_years_indx']

    yield1 = bf_signals_output['yield1']
    yield2 = bf_signals_output['yield2']

    yield1_current = bf_signals_output['yield1_current']
    yield2_current = bf_signals_output['yield2_current']

    yield1_last5_years = yield1[last5_years_indx]
    yield2_last5_years = yield2[last5_years_indx]

    plt.figure(figsize=(16,7))
    plt.scatter(yield2, yield1, color='b')
    plt.scatter(yield2_last5_years,yield1_last5_years, color='k')
    plt.scatter(yield2_current, yield1_current, color='r')
    plt.legend(['old', 'recent', 'last'], frameon=False)
    plt.grid()
    plt.show()

    return bf_signals_output
def generate_futures_butterfly_sheet_4date(**kwargs):

    date_to = kwargs['date_to']

    output_dir = ts.create_strategy_output_dir(
        strategy_class='futures_butterfly', report_date=date_to)

    if os.path.isfile(output_dir + '/summary.pkl'):
        butterflies = pd.read_pickle(output_dir + '/summary.pkl')
        return {'butterflies': butterflies, 'success': True}

    if 'volume_filter' not in kwargs.keys():
        kwargs['volume_filter'] = 100

    butterflies = get_futures_butterflies_4date(**kwargs)

    butterflies = butterflies[butterflies['trDte1'] >= 35]
    butterflies.reset_index(drop=True, inplace=True)
    num_butterflies = len(butterflies)

    q_list = [None] * num_butterflies
    qf_list = [None] * num_butterflies

    zscore1_list = [None] * num_butterflies
    zscore2_list = [None] * num_butterflies
    zscore3_list = [None] * num_butterflies
    zscore4_list = [None] * num_butterflies
    zscore5_list = [None] * num_butterflies
    zscore6_list = [None] * num_butterflies
    zscore7_list = [None] * num_butterflies

    rsquared1_list = [None] * num_butterflies
    rsquared2_list = [None] * num_butterflies

    regime_change_list = [None] * num_butterflies
    contract_seasonality_list = [None] * num_butterflies
    yield1_list = [None] * num_butterflies
    yield2_list = [None] * num_butterflies
    bf_price_list = [None] * num_butterflies
    bf_price_sell_limit_list = [None] * num_butterflies
    bf_price_buy_limit_list = [None] * num_butterflies
    noise_ratio_list = [None] * num_butterflies
    alpha1_list = [None] * num_butterflies
    alpha2_list = [None] * num_butterflies
    residual_std1_list = [None] * num_butterflies
    residual_std2_list = [None] * num_butterflies

    second_spread_weight_1_list = [None] * num_butterflies
    second_spread_weight_2_list = [None] * num_butterflies

    weight1_list = [None] * num_butterflies
    weight2_list = [None] * num_butterflies
    weight3_list = [None] * num_butterflies

    downside_list = [None] * num_butterflies
    upside_list = [None] * num_butterflies

    recent_5day_pnl_list = [None] * num_butterflies
    recent_vol_ratio_list = [None] * num_butterflies
    theo_pnl_list = [None] * num_butterflies

    theo_pnl5_list = [None] * num_butterflies
    theo_pnl10_list = [None] * num_butterflies
    theo_pnl15_list = [None] * num_butterflies
    theo_pnl20_list = [None] * num_butterflies
    theo_pnl25_list = [None] * num_butterflies

    ratio_target5_list = [None] * num_butterflies
    ratio_target10_list = [None] * num_butterflies
    ratio_target15_list = [None] * num_butterflies
    ratio_target20_list = [None] * num_butterflies
    ratio_target25_list = [None] * num_butterflies

    price_1_list = [None] * num_butterflies
    price_2_list = [None] * num_butterflies
    price_3_list = [None] * num_butterflies

    mean_reversion_rsquared_list = [None] * num_butterflies
    mean_reversion_signif_list = [None] * num_butterflies

    futures_data_dictionary = {
        x: gfp.get_futures_price_preloaded(ticker_head=x)
        for x in cmi.futures_butterfly_strategy_tickerhead_list
    }

    date5_years_ago = cu.doubledate_shift(date_to, 5 * 365)
    datetime5_years_ago = cu.convert_doubledate_2datetime(date5_years_ago)

    for i in range(num_butterflies):

        bf_signals_output = fs.get_futures_butterfly_signals(
            ticker_list=[
                butterflies['ticker1'][i], butterflies['ticker2'][i],
                butterflies['ticker3'][i]
            ],
            tr_dte_list=[
                butterflies['trDte1'][i], butterflies['trDte2'][i],
                butterflies['trDte3'][i]
            ],
            aggregation_method=butterflies['agg'][i],
            contracts_back=butterflies['cBack'][i],
            date_to=date_to,
            futures_data_dictionary=futures_data_dictionary,
            contract_multiplier=butterflies['multiplier'][i],
            datetime5_years_ago=datetime5_years_ago)

        if not bf_signals_output['success']:
            continue

        q_list[i] = bf_signals_output['q']
        qf_list[i] = bf_signals_output['qf']
        zscore1_list[i] = bf_signals_output['zscore1']
        zscore2_list[i] = bf_signals_output['zscore2']
        zscore3_list[i] = bf_signals_output['zscore3']
        zscore4_list[i] = bf_signals_output['zscore4']
        zscore5_list[i] = bf_signals_output['zscore5']
        zscore6_list[i] = bf_signals_output['zscore6']
        zscore7_list[i] = bf_signals_output['zscore7']
        rsquared1_list[i] = bf_signals_output['rsquared1']
        rsquared2_list[i] = bf_signals_output['rsquared2']

        regime_change_list[i] = bf_signals_output['regime_change_ind']
        contract_seasonality_list[i] = bf_signals_output[
            'contract_seasonality_ind']
        yield1_list[i] = bf_signals_output['yield1_current']
        yield2_list[i] = bf_signals_output['yield2_current']
        bf_price_list[i] = bf_signals_output['bf_price']
        bf_price_sell_limit_list[i] = bf_signals_output['short_price_limit']
        bf_price_buy_limit_list[i] = bf_signals_output['long_price_limit']
        noise_ratio_list[i] = bf_signals_output['noise_ratio']
        alpha1_list[i] = bf_signals_output['alpha1']
        alpha2_list[i] = bf_signals_output['alpha2']
        residual_std1_list = bf_signals_output['residual_std1']
        residual_std2_list = bf_signals_output['residual_std2']

        second_spread_weight_1_list[i] = bf_signals_output[
            'second_spread_weight_1']
        second_spread_weight_2_list[i] = bf_signals_output[
            'second_spread_weight_2']
        weight1_list[i] = bf_signals_output['weight1']
        weight2_list[i] = bf_signals_output['weight2']
        weight3_list[i] = bf_signals_output['weight3']

        downside_list[i] = bf_signals_output['downside']
        upside_list[i] = bf_signals_output['upside']

        recent_5day_pnl_list[i] = bf_signals_output['recent_5day_pnl']
        recent_vol_ratio_list[i] = bf_signals_output['recent_vol_ratio']
        theo_pnl_list[i] = bf_signals_output['theo_pnl']

        theo_pnl5_list[i] = bf_signals_output['theo_pnl_list'][0]
        theo_pnl10_list[i] = bf_signals_output['theo_pnl_list'][1]
        theo_pnl15_list[i] = bf_signals_output['theo_pnl_list'][2]
        theo_pnl20_list[i] = bf_signals_output['theo_pnl_list'][3]
        theo_pnl25_list[i] = bf_signals_output['theo_pnl_list'][4]

        ratio_target5_list[i] = bf_signals_output['ratio_target_list'][0]
        ratio_target10_list[i] = bf_signals_output['ratio_target_list'][1]
        ratio_target15_list[i] = bf_signals_output['ratio_target_list'][2]
        ratio_target20_list[i] = bf_signals_output['ratio_target_list'][3]
        ratio_target25_list[i] = bf_signals_output['ratio_target_list'][4]

        price_1_list[i] = bf_signals_output['price_1']
        price_2_list[i] = bf_signals_output['price_2']
        price_3_list[i] = bf_signals_output['price_3']

        mean_reversion_rsquared_list[i] = bf_signals_output[
            'mean_reversion_rsquared']
        mean_reversion_signif_list[i] = bf_signals_output[
            'mean_reversion_signif']

    butterflies['Q'] = q_list
    butterflies['QF'] = qf_list

    butterflies['z1'] = zscore1_list
    butterflies['z2'] = zscore2_list
    butterflies['z3'] = zscore3_list
    butterflies['z4'] = zscore4_list
    butterflies['z5'] = zscore5_list
    butterflies['z6'] = zscore6_list
    butterflies['z7'] = zscore7_list

    butterflies['r1'] = rsquared1_list
    butterflies['r2'] = rsquared2_list

    butterflies['RC'] = regime_change_list
    butterflies['seasonality'] = contract_seasonality_list
    butterflies['yield1'] = yield1_list
    butterflies['yield2'] = yield2_list
    butterflies['bf_price'] = bf_price_list
    butterflies['bf_sell_limit'] = bf_price_sell_limit_list
    butterflies['bf_buy_limit'] = bf_price_buy_limit_list
    butterflies['noise_ratio'] = noise_ratio_list
    butterflies['alpha1'] = alpha1_list
    butterflies['alpha2'] = alpha2_list

    butterflies['residual_std1'] = residual_std1_list
    butterflies['residual_std2'] = residual_std2_list

    butterflies['second_spread_weight_1'] = second_spread_weight_1_list
    butterflies['second_spread_weight_2'] = second_spread_weight_2_list

    butterflies['weight1'] = weight1_list
    butterflies['weight2'] = weight2_list
    butterflies['weight3'] = weight3_list
    butterflies['downside'] = downside_list
    butterflies['upside'] = upside_list

    butterflies['recent_5day_pnl'] = recent_5day_pnl_list
    butterflies['recent_vol_ratio'] = recent_vol_ratio_list
    butterflies['theo_pnl'] = theo_pnl_list

    butterflies['theo_pnl5'] = theo_pnl5_list
    butterflies['theo_pnl10'] = theo_pnl10_list
    butterflies['theo_pnl15'] = theo_pnl15_list
    butterflies['theo_pnl20'] = theo_pnl20_list
    butterflies['theo_pnl25'] = theo_pnl25_list

    butterflies['ratio_target5'] = ratio_target5_list
    butterflies['ratio_target10'] = ratio_target10_list
    butterflies['ratio_target15'] = ratio_target15_list
    butterflies['ratio_target20'] = ratio_target20_list
    butterflies['ratio_target25'] = ratio_target25_list

    butterflies['price1'] = price_1_list
    butterflies['price2'] = price_2_list
    butterflies['price3'] = price_3_list

    butterflies['mean_reversion_rsquared'] = mean_reversion_rsquared_list
    butterflies['mean_reversion_signif'] = mean_reversion_signif_list

    butterflies['z1'] = butterflies['z1'].round(2)
    butterflies['z2'] = butterflies['z2'].round(2)
    butterflies['z3'] = butterflies['z3'].round(2)
    butterflies['z4'] = butterflies['z4'].round(2)
    butterflies['z5'] = butterflies['z5'].round(2)
    butterflies['z6'] = butterflies['z6'].round(2)
    butterflies['z7'] = butterflies['z7'].round(2)
    butterflies['r1'] = butterflies['r1'].round(2)
    butterflies['r2'] = butterflies['r2'].round(2)
    butterflies['RC'] = butterflies['RC'].round(2)
    butterflies['seasonality'] = butterflies['seasonality'].round(2)
    butterflies['second_spread_weight_1'] = butterflies[
        'second_spread_weight_1'].round(2)
    butterflies['second_spread_weight_2'] = butterflies[
        'second_spread_weight_1'].round(2)

    butterflies['yield1'] = butterflies['yield1'].round(3)
    butterflies['yield2'] = butterflies['yield2'].round(3)

    butterflies['noise_ratio'] = butterflies['noise_ratio'].round(3)
    butterflies['alpha1'] = butterflies['alpha1'].round(3)
    butterflies['alpha2'] = butterflies['alpha2'].round(3)

    butterflies['residual_std1'] = butterflies['residual_std1'].round(3)
    butterflies['residual_std2'] = butterflies['residual_std2'].round(3)

    butterflies['downside'] = butterflies['downside'].round(3)
    butterflies['upside'] = butterflies['upside'].round(3)

    butterflies['recent_5day_pnl'] = butterflies['recent_5day_pnl'].round(3)
    butterflies['recent_vol_ratio'] = butterflies['recent_vol_ratio'].round(2)
    butterflies['theo_pnl'] = butterflies['theo_pnl'].round(3)

    butterflies['price1'] = butterflies['price1'].round(4)
    butterflies['price2'] = butterflies['price2'].round(4)
    butterflies['price3'] = butterflies['price3'].round(4)

    butterflies['mean_reversion_rsquared'] = butterflies[
        'mean_reversion_rsquared'].round(2)

    butterflies.to_pickle(output_dir + '/summary.pkl')

    return {'butterflies': butterflies, 'success': True}
Beispiel #6
0
def get_results_4strategy(**kwargs):

    signal_input = dict()

    if 'futures_data_dictionary' in kwargs.keys():
        signal_input['futures_data_dictionary'] = kwargs[
            'futures_data_dictionary']

    if 'date_to' in kwargs.keys():
        date_to = kwargs['date_to']
    else:
        date_to = exp.doubledate_shift_bus_days()

    if 'datetime5_years_ago' in kwargs.keys():
        signal_input['datetime5_years_ago'] = kwargs['datetime5_years_ago']

    if 'strategy_info_output' in kwargs.keys():
        strategy_info_output = kwargs['strategy_info_output']
    else:
        strategy_info_output = ts.get_strategy_info_from_alias(**kwargs)

    if 'broker' in kwargs.keys():
        broker = kwargs['broker']
    else:
        broker = 'abn'

    con = msu.get_my_sql_connection(**kwargs)

    strategy_info_dict = sc.convert_from_string_to_dictionary(
        string_input=strategy_info_output['description_string'])

    strategy_class = strategy_info_dict['strategy_class']

    pnl_frame = tpm.get_daily_pnl_snapshot(as_of_date=date_to, broker=broker)
    pnl_frame = pnl_frame[pnl_frame['alias'] == kwargs['alias']]
    strategy_position = ts.get_net_position_4strategy_alias(
        alias=kwargs['alias'], as_of_date=date_to)

    if strategy_class == 'futures_butterfly':

        ticker_head = cmi.get_contract_specs(
            strategy_info_dict['ticker1'])['ticker_head']
        if not strategy_position.empty:
            total_contracts2trade = strategy_position['qty'].abs().sum()
            t_cost = cmi.t_cost[ticker_head]
        QF_initial = float(strategy_info_dict['QF'])
        z1_initial = float(strategy_info_dict['z1'])

        bf_signals_output = fs.get_futures_butterfly_signals(
            ticker_list=[
                strategy_info_dict['ticker1'], strategy_info_dict['ticker2'],
                strategy_info_dict['ticker3']
            ],
            aggregation_method=int(strategy_info_dict['agg']),
            contracts_back=int(strategy_info_dict['cBack']),
            date_to=date_to,
            **signal_input)

        if bf_signals_output['success']:
            aligned_output = bf_signals_output['aligned_output']
            current_data = aligned_output['current_data']
            holding_tr_dte = int(
                strategy_info_dict['trDte1']) - current_data['c1']['tr_dte']
            success_status = True
            QF = bf_signals_output['qf']
            z1 = bf_signals_output['zscore1']
            short_tr_dte = current_data['c1']['tr_dte']
            second_spread_weight = bf_signals_output['second_spread_weight_1']

            if strategy_position.empty:
                recommendation = 'CLOSE'
            elif (z1_initial>0)&(holding_tr_dte > 5) &\
                    (bf_signals_output['qf']<QF_initial-20)&\
                    (pnl_frame['total_pnl'].iloc[0] > 3*t_cost*total_contracts2trade):
                recommendation = 'STOP'
            elif (z1_initial<0)&(holding_tr_dte > 5) &\
                    (bf_signals_output['qf']>QF_initial+20)&\
                    (pnl_frame['total_pnl'].iloc[0] > 3*t_cost*total_contracts2trade):
                recommendation = 'STOP'
            elif (current_data['c1']['tr_dte'] < 35)&\
                (pnl_frame['total_pnl'].iloc[0] > 3*t_cost*total_contracts2trade):
                recommendation = 'STOP'
            elif (current_data['c1']['tr_dte'] < 35)&\
                (pnl_frame['total_pnl'].iloc[0] < 3*t_cost*total_contracts2trade):
                recommendation = 'WINDDOWN'
            else:
                recommendation = 'HOLD'
        else:
            success_status = False
            QF = np.nan
            z1 = np.nan
            short_tr_dte = np.nan
            holding_tr_dte = np.nan
            second_spread_weight = np.nan
            recommendation = 'MISSING DATA'

        result_output = {
            'success': success_status,
            'ticker_head': ticker_head,
            'QF_initial': QF_initial,
            'z1_initial': z1_initial,
            'QF': QF,
            'z1': z1,
            'short_tr_dte': short_tr_dte,
            'holding_tr_dte': holding_tr_dte,
            'second_spread_weight': second_spread_weight,
            'recommendation': recommendation
        }

    elif strategy_class == 'spread_carry':
        trades4_strategy = ts.get_trades_4strategy_alias(**kwargs)
        grouped = trades4_strategy.groupby('ticker')
        net_position = pd.DataFrame()
        net_position['ticker'] = (grouped['ticker'].first()).values
        net_position['qty'] = (grouped['trade_quantity'].sum()).values
        net_position = net_position[net_position['qty'] != 0]

        net_position['ticker_head'] = [
            cmi.get_contract_specs(x)['ticker_head']
            for x in net_position['ticker']
        ]
        price_output = [
            gfp.get_futures_price_preloaded(ticker=x, settle_date=date_to)
            for x in net_position['ticker']
        ]
        net_position['tr_dte'] = [
            np.nan if x.empty else x['tr_dte'].values[0] for x in price_output
        ]

        results_frame = pd.DataFrame()
        unique_tickerhead_list = net_position['ticker_head'].unique()
        results_frame['tickerHead'] = unique_tickerhead_list
        results_frame['ticker1'] = [None] * len(unique_tickerhead_list)
        results_frame['ticker2'] = [None] * len(unique_tickerhead_list)
        results_frame['qty'] = [None] * len(unique_tickerhead_list)
        results_frame['pnl'] = [None] * len(unique_tickerhead_list)
        results_frame['downside'] = [None] * len(unique_tickerhead_list)
        results_frame['indicator'] = [None] * len(unique_tickerhead_list)
        results_frame['timeHeld'] = [None] * len(unique_tickerhead_list)
        results_frame['recommendation'] = [None] * len(unique_tickerhead_list)

        spread_carry_output = osc.generate_spread_carry_sheet_4date(
            report_date=date_to)
        spread_report = spread_carry_output['spread_report']

        pnl_output = tpnl.get_strategy_pnl(**kwargs)
        pnl_per_tickerhead = pnl_output['pnl_per_tickerhead']

        for i in range(len(unique_tickerhead_list)):
            net_position_per_tickerhead = net_position[
                net_position['ticker_head'] == unique_tickerhead_list[i]]
            net_position_per_tickerhead.sort_values('tr_dte',
                                                    ascending=True,
                                                    inplace=True)

            selected_spread = spread_report[
                (spread_report['ticker1'] ==
                 net_position_per_tickerhead['ticker'].values[0])
                & (spread_report['ticker2'] ==
                   net_position_per_tickerhead['ticker'].values[1])]

            results_frame['qty'][i] = net_position_per_tickerhead[
                'qty'].values[0]

            if selected_spread.empty:
                results_frame['ticker1'][i] = net_position_per_tickerhead[
                    'ticker'].values[0]
                results_frame['ticker2'][i] = net_position_per_tickerhead[
                    'ticker'].values[1]
            else:
                results_frame['ticker1'][i] = selected_spread[
                    'ticker1'].values[0]
                results_frame['ticker2'][i] = selected_spread[
                    'ticker2'].values[0]

                selected_trades = trades4_strategy[
                    trades4_strategy['ticker'] ==
                    results_frame['ticker1'].values[i]]

                price_output = gfp.get_futures_price_preloaded(
                    ticker=results_frame['ticker1'].values[i],
                    settle_date=pd.to_datetime(
                        selected_trades['trade_date'].values[0]))

                results_frame['timeHeld'][i] = price_output['tr_dte'].values[
                    0] - net_position_per_tickerhead['tr_dte'].values[0]
                results_frame['pnl'][i] = pnl_per_tickerhead[
                    unique_tickerhead_list[i]].sum()

                if unique_tickerhead_list[i] in ['CL', 'B', 'ED']:
                    results_frame['indicator'][i] = selected_spread[
                        'reward_risk'].values[0]

                    if results_frame['qty'][i] > 0:
                        results_frame['recommendation'][i] = 'STOP'
                    elif results_frame['qty'][i] < 0:
                        if results_frame['indicator'][i] > -0.06:
                            results_frame['recommendation'][i] = 'STOP'
                        else:
                            results_frame['recommendation'][i] = 'HOLD'
                else:

                    results_frame['indicator'][i] = selected_spread[
                        'q_carry'].values[0]

                    if results_frame['qty'][i] > 0:
                        if results_frame['indicator'][i] < 19:
                            results_frame['recommendation'][i] = 'STOP'
                        else:
                            results_frame['recommendation'][i] = 'HOLD'

                    elif results_frame['qty'][i] < 0:
                        if results_frame['indicator'][i] > -9:
                            results_frame['recommendation'][i] = 'STOP'
                        else:
                            results_frame['recommendation'][i] = 'HOLD'

                if results_frame['qty'][i] > 0:
                    results_frame['downside'][i] = selected_spread[
                        'downside'].values[0] * results_frame['qty'][i]
                else:
                    results_frame['downside'][i] = selected_spread[
                        'upside'].values[0] * results_frame['qty'][i]

        return {'success': True, 'results_frame': results_frame}

    elif strategy_class == 'vcs':

        greeks_out = sg.get_greeks_4strategy_4date(alias=kwargs['alias'],
                                                   as_of_date=date_to)
        ticker_portfolio = greeks_out['ticker_portfolio']
        options_position = greeks_out['options_position']

        if ticker_portfolio.empty and not options_position.empty:
            result_output = {
                'success': False,
                'net_oev': np.NaN,
                'net_theta': np.NaN,
                'long_short_ratio': np.NaN,
                'recommendation': 'MISSING DATA',
                'last_adjustment_days_ago': np.NaN,
                'min_tr_dte': np.NaN,
                'long_oev': np.NaN,
                'short_oev': np.NaN,
                'favQMove': np.NaN
            }
        elif ticker_portfolio.empty and options_position.empty:
            result_output = {
                'success': False,
                'net_oev': np.NaN,
                'net_theta': np.NaN,
                'long_short_ratio': np.NaN,
                'recommendation': 'EMPTY',
                'last_adjustment_days_ago': np.NaN,
                'min_tr_dte': np.NaN,
                'long_oev': np.NaN,
                'short_oev': np.NaN,
                'favQMove': np.NaN
            }

        else:
            min_tr_dte = min([
                exp.get_days2_expiration(ticker=x,
                                         date_to=date_to,
                                         instrument='options',
                                         con=con)['tr_dte']
                for x in ticker_portfolio['ticker']
            ])

            net_oev = ticker_portfolio['total_oev'].sum()
            net_theta = ticker_portfolio['theta'].sum()

            long_portfolio = ticker_portfolio[
                ticker_portfolio['total_oev'] > 0]
            short_portfolio = ticker_portfolio[
                ticker_portfolio['total_oev'] < 0]
            short_portfolio['total_oev'] = abs(short_portfolio['total_oev'])

            long_oev = long_portfolio['total_oev'].sum()
            short_oev = short_portfolio['total_oev'].sum()

            if (not short_portfolio.empty) & (not long_portfolio.empty):
                long_short_ratio = 100 * long_oev / short_oev

                long_portfolio.sort_values('total_oev',
                                           ascending=False,
                                           inplace=True)
                short_portfolio.sort_values('total_oev',
                                            ascending=False,
                                            inplace=True)

                long_ticker = long_portfolio['ticker'].iloc[0]
                short_ticker = short_portfolio['ticker'].iloc[0]

                long_contract_specs = cmi.get_contract_specs(long_ticker)
                short_contract_specs = cmi.get_contract_specs(short_ticker)

                if 12*long_contract_specs['ticker_year']+long_contract_specs['ticker_month_num'] < \
                                        12*short_contract_specs['ticker_year']+short_contract_specs['ticker_month_num']:
                    front_ticker = long_ticker
                    back_ticker = short_ticker
                    direction = 'long'
                else:
                    front_ticker = short_ticker
                    back_ticker = long_ticker
                    direction = 'short'

                if 'vcs_output' in kwargs.keys():
                    vcs_output = kwargs['vcs_output']
                else:
                    vcs_output = ovcs.generate_vcs_sheet_4date(date_to=date_to)

                vcs_pairs = vcs_output['vcs_pairs']
                selected_result = vcs_pairs[
                    (vcs_pairs['ticker1'] == front_ticker)
                    & (vcs_pairs['ticker2'] == back_ticker)]

                if selected_result.empty:
                    favQMove = np.NaN
                else:
                    current_Q = selected_result['Q'].iloc[0]
                    q_limit = of.get_vcs_filter_values(
                        product_group=long_contract_specs['ticker_head'],
                        filter_type='tickerHead',
                        direction=direction,
                        indicator='Q')
                    if direction == 'long':
                        favQMove = current_Q - q_limit
                    elif direction == 'short':
                        favQMove = q_limit - current_Q
            else:
                long_short_ratio = np.NaN
                favQMove = np.NaN

            trades_frame = ts.get_trades_4strategy_alias(**kwargs)
            trades_frame_options = trades_frame[trades_frame['instrument'] ==
                                                'O']
            last_adjustment_days_ago = len(
                exp.get_bus_day_list(
                    date_to=date_to,
                    datetime_from=max(
                        trades_frame_options['trade_date']).to_pydatetime()))

            if favQMove >= 10 and last_adjustment_days_ago > 10:
                recommendation = 'STOP-ratio normalized'
            elif min_tr_dte < 25:
                recommendation = 'STOP-close to expiration'
            elif np.isnan(long_short_ratio):
                recommendation = 'STOP-not a proper calendar'
            else:
                if long_short_ratio < 80:
                    if favQMove < 0:
                        recommendation = 'buy_options_to_grow'
                    else:
                        recommendation = 'buy_options_to_shrink'
                elif long_short_ratio > 120:
                    if favQMove < 0:
                        recommendation = 'sell_options_to_grow'
                    else:
                        recommendation = 'sell_options_to_shrink'
                else:
                    recommendation = 'HOLD'

            result_output = {
                'success': True,
                'net_oev': net_oev,
                'net_theta': net_theta,
                'long_short_ratio': long_short_ratio,
                'recommendation': recommendation,
                'last_adjustment_days_ago': last_adjustment_days_ago,
                'min_tr_dte': min_tr_dte,
                'long_oev': long_oev,
                'short_oev': short_oev,
                'favQMove': favQMove
            }

    elif strategy_class == 'ocs':

        datetime_to = cu.convert_doubledate_2datetime(date_to)
        time_held = (datetime_to.date() -
                     strategy_info_output['created_date'].date()).days
        notes = ''

        strategy_position = ts.get_net_position_4strategy_alias(
            alias=kwargs['alias'], as_of_date=date_to, con=con)

        if len(strategy_position.index) == 0:
            tpnl.close_strategy(alias=kwargs['alias'],
                                close_date=date_to,
                                broker=broker,
                                con=con)
            result_output = {
                'success': True,
                'time_held': time_held,
                'dollar_noise': np.nan,
                'notes': 'closed'
            }
        elif strategy_position['qty'].sum() != 0:
            result_output = {
                'success': True,
                'time_held': time_held,
                'dollar_noise': np.nan,
                'notes': 'check position'
            }
        else:
            strategy_position['cont_indx'] = [
                cmi.get_contract_specs(x)['cont_indx']
                for x in strategy_position['ticker']
            ]
            strategy_position.sort_values('cont_indx',
                                          ascending=True,
                                          inplace=True)

            ocs_output = ocs.generate_overnight_spreads_sheet_4date(
                date_to=date_to)
            overnight_calendars = ocs_output['overnight_calendars']

            selection_indx = (overnight_calendars['ticker1'] == strategy_position['ticker'].iloc[0])&\
                             (overnight_calendars['ticker2'] == strategy_position['ticker'].iloc[1])

            if sum(selection_indx) > 0:
                dollar_noise = (overnight_calendars.loc[
                    selection_indx, 'dollarNoise100'].values[0]) * abs(
                        strategy_position['qty'].iloc[0])
            else:
                dollar_noise = np.nan

            result_output = {
                'success': True,
                'time_held': time_held,
                'dollar_noise': dollar_noise,
                'notes': 'hold'
            }

    elif strategy_class == 'skpt':

        long_ticker = strategy_position.loc[strategy_position['qty'] > 0,
                                            'ticker'].iloc[0]
        short_ticker = strategy_position.loc[strategy_position['qty'] < 0,
                                             'ticker'].iloc[0]

        long_data = gsp.get_stock_price_preloaded(ticker=long_ticker,
                                                  data_source='iex',
                                                  settle_date_to=date_to)
        short_data = gsp.get_stock_price_preloaded(ticker=short_ticker,
                                                   data_source='iex',
                                                   settle_date_to=date_to)
        merged_data = pd.merge(long_data[['close', 'settle_datetime']],
                               short_data[['close', 'settle_datetime']],
                               how='inner',
                               on='settle_datetime')
        merged_data.set_index('settle_datetime', drop=True, inplace=True)

        intaday_output_long = pweb.DataReader(long_ticker, 'iex-tops')
        intaday_output_short = pweb.DataReader(short_ticker, 'iex-tops')
        merged_data = merged_data.append(
            pd.DataFrame(
                {
                    'close_x': intaday_output_long.iloc[4].values[0],
                    'close_y': intaday_output_short.iloc[4].values[0]
                },
                index=[dt.datetime.now()]))

        signal_output = spt.backtest(merged_data, 'close_x', 'close_y')

        return {
            'long_ticker': long_ticker,
            'short_ticker': short_ticker,
            'zScoreC': signal_output['data_frame']['zScore'].iloc[-1],
            'zScore': signal_output['data_frame']['zScore'].iloc[-2]
        }

    else:
        result_output = {'success': False}

    if 'con' not in kwargs.keys():
        con.close()

    return result_output
def generate_futures_butterfly_sheet_4date(**kwargs):

    date_to = kwargs['date_to']

    output_dir = ts.create_strategy_output_dir(strategy_class='futures_butterfly', report_date=date_to)

    if os.path.isfile(output_dir + '/summary.pkl'):
        butterflies = pd.read_pickle(output_dir + '/summary.pkl')
        return {'butterflies': butterflies,'success': True}

    if 'volume_filter' not in kwargs.keys():
        kwargs['volume_filter'] = 100

    butterflies = get_futures_butterflies_4date(**kwargs)

    butterflies = butterflies[butterflies['trDte1'] >= 35]
    butterflies.reset_index(drop=True,inplace=True)
    num_butterflies = len(butterflies)

    q_list = [None]*num_butterflies
    qf_list = [None]*num_butterflies

    zscore1_list = [None]*num_butterflies
    zscore2_list = [None]*num_butterflies
    zscore3_list = [None]*num_butterflies
    zscore4_list = [None]*num_butterflies
    zscore5_list = [None]*num_butterflies
    zscore6_list = [None]*num_butterflies
    zscore7_list = [None]*num_butterflies

    rsquared1_list = [None]*num_butterflies
    rsquared2_list = [None]*num_butterflies

    regime_change_list = [None]*num_butterflies
    contract_seasonality_list = [None]*num_butterflies
    yield1_list = [None]*num_butterflies
    yield2_list = [None]*num_butterflies
    bf_price_list = [None]*num_butterflies
    bf_price_sell_limit_list = [None]*num_butterflies
    bf_price_buy_limit_list = [None]*num_butterflies
    noise_ratio_list = [None]*num_butterflies
    alpha1_list = [None]*num_butterflies
    alpha2_list = [None]*num_butterflies
    residual_std1_list = [None]*num_butterflies
    residual_std2_list = [None]*num_butterflies

    second_spread_weight_1_list = [None]*num_butterflies
    second_spread_weight_2_list = [None]*num_butterflies

    weight1_list = [None]*num_butterflies
    weight2_list = [None]*num_butterflies
    weight3_list = [None]*num_butterflies

    downside_list = [None]*num_butterflies
    upside_list = [None]*num_butterflies

    recent_5day_pnl_list = [None]*num_butterflies
    recent_vol_ratio_list = [None]*num_butterflies
    theo_pnl_list = [None]*num_butterflies

    theo_pnl5_list = [None]*num_butterflies
    theo_pnl10_list = [None]*num_butterflies
    theo_pnl15_list = [None]*num_butterflies
    theo_pnl20_list = [None]*num_butterflies
    theo_pnl25_list = [None]*num_butterflies

    ratio_target5_list = [None]*num_butterflies
    ratio_target10_list = [None]*num_butterflies
    ratio_target15_list = [None]*num_butterflies
    ratio_target20_list = [None]*num_butterflies
    ratio_target25_list = [None]*num_butterflies

    price_1_list = [None]*num_butterflies
    price_2_list = [None]*num_butterflies
    price_3_list = [None]*num_butterflies

    mean_reversion_rsquared_list = [None]*num_butterflies
    mean_reversion_signif_list = [None]*num_butterflies

    futures_data_dictionary = {x: gfp.get_futures_price_preloaded(ticker_head=x) for x in cmi.futures_butterfly_strategy_tickerhead_list}

    date5_years_ago = cu.doubledate_shift(date_to,5*365)
    datetime5_years_ago = cu.convert_doubledate_2datetime(date5_years_ago)

    for i in range(num_butterflies):
        bf_signals_output = fs.get_futures_butterfly_signals(ticker_list=[butterflies['ticker1'][i], butterflies['ticker2'][i], butterflies['ticker3'][i]],
                                          tr_dte_list=[butterflies['trDte1'][i], butterflies['trDte2'][i], butterflies['trDte3'][i]],
                                          aggregation_method=butterflies['agg'][i],
                                          contracts_back=butterflies['cBack'][i],
                                          date_to=date_to,
                                          futures_data_dictionary=futures_data_dictionary,
                                          contract_multiplier=butterflies['multiplier'][i],
                                          datetime5_years_ago=datetime5_years_ago)

        q_list[i] = bf_signals_output['q']
        qf_list[i] = bf_signals_output['qf']
        zscore1_list[i] = bf_signals_output['zscore1']
        zscore2_list[i] = bf_signals_output['zscore2']
        zscore3_list[i] = bf_signals_output['zscore3']
        zscore4_list[i] = bf_signals_output['zscore4']
        zscore5_list[i] = bf_signals_output['zscore5']
        zscore6_list[i] = bf_signals_output['zscore6']
        zscore7_list[i] = bf_signals_output['zscore7']
        rsquared1_list[i] = bf_signals_output['rsquared1']
        rsquared2_list[i] = bf_signals_output['rsquared2']

        regime_change_list[i] = bf_signals_output['regime_change_ind']
        contract_seasonality_list[i] = bf_signals_output['contract_seasonality_ind']
        yield1_list[i] = bf_signals_output['yield1_current']
        yield2_list[i] = bf_signals_output['yield2_current']
        bf_price_list[i] = bf_signals_output['bf_price']
        bf_price_sell_limit_list[i] = bf_signals_output['short_price_limit']
        bf_price_buy_limit_list[i] = bf_signals_output['long_price_limit']
        noise_ratio_list[i] = bf_signals_output['noise_ratio']
        alpha1_list[i] = bf_signals_output['alpha1']
        alpha2_list[i] = bf_signals_output['alpha2']
        residual_std1_list = bf_signals_output['residual_std1']
        residual_std2_list = bf_signals_output['residual_std2']

        second_spread_weight_1_list[i] = bf_signals_output['second_spread_weight_1']
        second_spread_weight_2_list[i] = bf_signals_output['second_spread_weight_2']
        weight1_list[i] = bf_signals_output['weight1']
        weight2_list[i] = bf_signals_output['weight2']
        weight3_list[i] = bf_signals_output['weight3']

        downside_list[i] = bf_signals_output['downside']
        upside_list[i] = bf_signals_output['upside']

        recent_5day_pnl_list[i] = bf_signals_output['recent_5day_pnl']
        recent_vol_ratio_list[i] = bf_signals_output['recent_vol_ratio']
        theo_pnl_list[i] = bf_signals_output['theo_pnl']

        theo_pnl5_list[i] = bf_signals_output['theo_pnl_list'][0]
        theo_pnl10_list[i] = bf_signals_output['theo_pnl_list'][1]
        theo_pnl15_list[i] = bf_signals_output['theo_pnl_list'][2]
        theo_pnl20_list[i] = bf_signals_output['theo_pnl_list'][3]
        theo_pnl25_list[i] = bf_signals_output['theo_pnl_list'][4]

        ratio_target5_list[i] = bf_signals_output['ratio_target_list'][0]
        ratio_target10_list[i] = bf_signals_output['ratio_target_list'][1]
        ratio_target15_list[i] = bf_signals_output['ratio_target_list'][2]
        ratio_target20_list[i] = bf_signals_output['ratio_target_list'][3]
        ratio_target25_list[i] = bf_signals_output['ratio_target_list'][4]

        price_1_list[i] = bf_signals_output['price_1']
        price_2_list[i] = bf_signals_output['price_2']
        price_3_list[i] = bf_signals_output['price_3']

        mean_reversion_rsquared_list[i] = bf_signals_output['mean_reversion_rsquared']
        mean_reversion_signif_list[i] = bf_signals_output['mean_reversion_signif']

    butterflies['Q'] = q_list
    butterflies['QF'] = qf_list

    butterflies['z1'] = zscore1_list
    butterflies['z2'] = zscore2_list
    butterflies['z3'] = zscore3_list
    butterflies['z4'] = zscore4_list
    butterflies['z5'] = zscore5_list
    butterflies['z6'] = zscore6_list
    butterflies['z7'] = zscore7_list

    butterflies['r1'] = rsquared1_list
    butterflies['r2'] = rsquared2_list

    butterflies['RC'] = regime_change_list
    butterflies['seasonality'] = contract_seasonality_list
    butterflies['yield1'] = yield1_list
    butterflies['yield2'] = yield2_list
    butterflies['bf_price'] = bf_price_list
    butterflies['bf_sell_limit'] = bf_price_sell_limit_list
    butterflies['bf_buy_limit'] = bf_price_buy_limit_list
    butterflies['noise_ratio'] = noise_ratio_list
    butterflies['alpha1'] = alpha1_list
    butterflies['alpha2'] = alpha2_list

    butterflies['residual_std1'] = residual_std1_list
    butterflies['residual_std2'] = residual_std2_list

    butterflies['second_spread_weight_1'] = second_spread_weight_1_list
    butterflies['second_spread_weight_2'] = second_spread_weight_2_list

    butterflies['weight1'] = weight1_list
    butterflies['weight2'] = weight2_list
    butterflies['weight3'] = weight3_list
    butterflies['downside'] = downside_list
    butterflies['upside'] = upside_list

    butterflies['recent_5day_pnl'] = recent_5day_pnl_list
    butterflies['recent_vol_ratio'] = recent_vol_ratio_list
    butterflies['theo_pnl'] = theo_pnl_list

    butterflies['theo_pnl5'] = theo_pnl5_list
    butterflies['theo_pnl10'] = theo_pnl10_list
    butterflies['theo_pnl15'] = theo_pnl15_list
    butterflies['theo_pnl20'] = theo_pnl20_list
    butterflies['theo_pnl25'] = theo_pnl25_list

    butterflies['ratio_target5'] = ratio_target5_list
    butterflies['ratio_target10'] = ratio_target10_list
    butterflies['ratio_target15'] = ratio_target15_list
    butterflies['ratio_target20'] = ratio_target20_list
    butterflies['ratio_target25'] = ratio_target25_list

    butterflies['price1'] = price_1_list
    butterflies['price2'] = price_2_list
    butterflies['price3'] = price_3_list

    butterflies['mean_reversion_rsquared'] = mean_reversion_rsquared_list
    butterflies['mean_reversion_signif'] = mean_reversion_signif_list

    butterflies['z1'] = butterflies['z1'].round(2)
    butterflies['z2'] = butterflies['z2'].round(2)
    butterflies['z3'] = butterflies['z3'].round(2)
    butterflies['z4'] = butterflies['z4'].round(2)
    butterflies['z5'] = butterflies['z5'].round(2)
    butterflies['z6'] = butterflies['z6'].round(2)
    butterflies['z7'] = butterflies['z7'].round(2)
    butterflies['r1'] = butterflies['r1'].round(2)
    butterflies['r2'] = butterflies['r2'].round(2)
    butterflies['RC'] = butterflies['RC'].round(2)
    butterflies['seasonality'] = butterflies['seasonality'].round(2)
    butterflies['second_spread_weight_1'] = butterflies['second_spread_weight_1'].round(2)
    butterflies['second_spread_weight_2'] = butterflies['second_spread_weight_1'].round(2)

    butterflies['yield1'] = butterflies['yield1'].round(3)
    butterflies['yield2'] = butterflies['yield2'].round(3)

    butterflies['noise_ratio'] = butterflies['noise_ratio'].round(3)
    butterflies['alpha1'] = butterflies['alpha1'].round(3)
    butterflies['alpha2'] = butterflies['alpha2'].round(3)

    butterflies['residual_std1'] = butterflies['residual_std1'].round(3)
    butterflies['residual_std2'] = butterflies['residual_std2'].round(3)

    butterflies['downside'] = butterflies['downside'].round(3)
    butterflies['upside'] = butterflies['upside'].round(3)

    butterflies['recent_5day_pnl'] = butterflies['recent_5day_pnl'].round(3)
    butterflies['recent_vol_ratio'] = butterflies['recent_vol_ratio'].round(2)
    butterflies['theo_pnl'] = butterflies['theo_pnl'].round(3)

    butterflies['price1'] = butterflies['price1'].round(4)
    butterflies['price2'] = butterflies['price2'].round(4)
    butterflies['price3'] = butterflies['price3'].round(4)

    butterflies['mean_reversion_rsquared'] = butterflies['mean_reversion_rsquared'].round(2)

    butterflies.to_pickle(output_dir + '/summary.pkl')

    return {'butterflies': butterflies,'success': True}
def get_results_4strategy(**kwargs):

    signal_input = dict()

    if 'futures_data_dictionary' in kwargs.keys():
        signal_input['futures_data_dictionary'] = kwargs['futures_data_dictionary']

    if 'date_to' in kwargs.keys():
        date_to = kwargs['date_to']
    else:
        date_to = exp.doubledate_shift_bus_days()

    if 'datetime5_years_ago' in kwargs.keys():
        signal_input['datetime5_years_ago'] = kwargs['datetime5_years_ago']

    if 'strategy_info_output' in kwargs.keys():
        strategy_info_output = kwargs['strategy_info_output']
    else:
        strategy_info_output = ts.get_strategy_info_from_alias(**kwargs)

    con = msu.get_my_sql_connection(**kwargs)

    strategy_info_dict = sc.convert_from_string_to_dictionary(string_input=strategy_info_output['description_string'])
    #print(kwargs['alias'])

    strategy_class = strategy_info_dict['strategy_class']

    pnl_frame = tpm.get_daily_pnl_snapshot(as_of_date=date_to)
    pnl_frame = pnl_frame[pnl_frame['alias']==kwargs['alias']]
    strategy_position = ts.get_net_position_4strategy_alias(alias=kwargs['alias'],as_of_date=date_to)

    if strategy_class == 'futures_butterfly':

        ticker_head = cmi.get_contract_specs(strategy_info_dict['ticker1'])['ticker_head']
        if not strategy_position.empty:
            total_contracts2trade = strategy_position['qty'].abs().sum()
            t_cost = cmi.t_cost[ticker_head]
        QF_initial = float(strategy_info_dict['QF'])
        z1_initial = float(strategy_info_dict['z1'])

        bf_signals_output = fs.get_futures_butterfly_signals(ticker_list=[strategy_info_dict['ticker1'],
                                                                          strategy_info_dict['ticker2'],
                                                                          strategy_info_dict['ticker3']],
                                          aggregation_method=int(strategy_info_dict['agg']),
                                          contracts_back=int(strategy_info_dict['cBack']),
                                          date_to=date_to,**signal_input)

        aligned_output = bf_signals_output['aligned_output']
        current_data = aligned_output['current_data']
        holding_tr_dte = int(strategy_info_dict['trDte1'])-current_data['c1']['tr_dte']

        if strategy_position.empty:
            recommendation = 'CLOSE'
        elif (z1_initial>0)&(holding_tr_dte > 5) &\
                (bf_signals_output['qf']<QF_initial-20)&\
                (pnl_frame['total_pnl'].iloc[0] > 3*t_cost*total_contracts2trade):
            recommendation = 'STOP'
        elif (z1_initial<0)&(holding_tr_dte > 5) &\
                (bf_signals_output['qf']>QF_initial+20)&\
                (pnl_frame['total_pnl'].iloc[0] > 3*t_cost*total_contracts2trade):
            recommendation = 'STOP'
        elif (current_data['c1']['tr_dte'] < 35)&\
            (pnl_frame['total_pnl'].iloc[0] > 3*t_cost*total_contracts2trade):
            recommendation = 'STOP'
        elif (current_data['c1']['tr_dte'] < 35)&\
            (pnl_frame['total_pnl'].iloc[0] < 3*t_cost*total_contracts2trade):
            recommendation = 'WINDDOWN'
        else:
            recommendation = 'HOLD'

        result_output = {'success': True,'ticker_head': ticker_head,
                        'QF_initial':QF_initial,'z1_initial': z1_initial,
                        'QF': bf_signals_output['qf'],'z1': bf_signals_output['zscore1'],
                        'short_tr_dte': current_data['c1']['tr_dte'],
                        'holding_tr_dte': holding_tr_dte,
                        'second_spread_weight': bf_signals_output['second_spread_weight_1'],'recommendation': recommendation}

    elif strategy_class == 'spread_carry':
        trades4_strategy = ts.get_trades_4strategy_alias(**kwargs)
        grouped = trades4_strategy.groupby('ticker')
        net_position = pd.DataFrame()
        net_position['ticker'] = (grouped['ticker'].first()).values
        net_position['qty'] = (grouped['trade_quantity'].sum()).values
        net_position = net_position[net_position['qty'] != 0]

        net_position['ticker_head'] = [cmi.get_contract_specs(x)['ticker_head'] for x in net_position['ticker']]
        price_output = [gfp.get_futures_price_preloaded(ticker=x, settle_date=date_to) for x in net_position['ticker']]
        net_position['tr_dte'] = [x['tr_dte'].values[0] for x in price_output]

        results_frame = pd.DataFrame()
        unique_tickerhead_list = net_position['ticker_head'].unique()
        results_frame['tickerHead'] = unique_tickerhead_list
        results_frame['ticker1'] = [None]*len(unique_tickerhead_list)
        results_frame['ticker2'] = [None]*len(unique_tickerhead_list)
        results_frame['qty'] = [None]*len(unique_tickerhead_list)
        results_frame['pnl'] = [None]*len(unique_tickerhead_list)
        results_frame['downside'] = [None]*len(unique_tickerhead_list)
        results_frame['indicator'] = [None]*len(unique_tickerhead_list)
        results_frame['timeHeld'] = [None]*len(unique_tickerhead_list)
        results_frame['recommendation'] = [None]*len(unique_tickerhead_list)

        spread_carry_output = osc.generate_spread_carry_sheet_4date(report_date=date_to)
        spread_report = spread_carry_output['spread_report']

        pnl_output = tpnl.get_strategy_pnl(**kwargs)
        pnl_per_tickerhead = pnl_output['pnl_per_tickerhead']

        for i in range(len(unique_tickerhead_list)):

            net_position_per_tickerhead = net_position[net_position['ticker_head'] == unique_tickerhead_list[i]]
            net_position_per_tickerhead.sort('tr_dte',ascending=True,inplace=True)

            selected_spread = spread_report[(spread_report['ticker1'] == net_position_per_tickerhead['ticker'].values[0]) &
                             (spread_report['ticker2'] == net_position_per_tickerhead['ticker'].values[1])]

            results_frame['ticker1'][i] = selected_spread['ticker1'].values[0]
            results_frame['ticker2'][i] = selected_spread['ticker2'].values[0]
            results_frame['qty'][i] = net_position_per_tickerhead['qty'].values[0]

            selected_trades = trades4_strategy[trades4_strategy['ticker'] == results_frame['ticker1'].values[i]]

            price_output = gfp.get_futures_price_preloaded(ticker=results_frame['ticker1'].values[i],
                                                           settle_date=pd.to_datetime(selected_trades['trade_date'].values[0]))

            results_frame['timeHeld'][i] = price_output['tr_dte'].values[0]-net_position_per_tickerhead['tr_dte'].values[0]
            results_frame['pnl'][i] = pnl_per_tickerhead[unique_tickerhead_list[i]].sum()

            if unique_tickerhead_list[i] in ['CL', 'B', 'ED']:
                results_frame['indicator'][i] = selected_spread['reward_risk'].values[0]

                if results_frame['qty'][i] > 0:
                    results_frame['recommendation'][i] = 'STOP'
                elif results_frame['qty'][i] < 0:
                    if results_frame['indicator'][i] > -0.06:
                        results_frame['recommendation'][i] = 'STOP'
                    else:
                        results_frame['recommendation'][i] = 'HOLD'
            else:

                results_frame['indicator'][i] = selected_spread['q_carry'].values[0]

                if results_frame['qty'][i] > 0:
                    if results_frame['indicator'][i] < 19:
                        results_frame['recommendation'][i] = 'STOP'
                    else:
                        results_frame['recommendation'][i] = 'HOLD'

                elif results_frame['qty'][i] < 0:
                    if results_frame['indicator'][i] > -9:
                        results_frame['recommendation'][i] = 'STOP'
                    else:
                        results_frame['recommendation'][i] = 'HOLD'

            if results_frame['qty'][i] > 0:
                results_frame['downside'][i] = selected_spread['downside'].values[0]*results_frame['qty'][i]
            else:
                results_frame['downside'][i] = selected_spread['upside'].values[0]*results_frame['qty'][i]

        return {'success': True, 'results_frame': results_frame}

    elif strategy_class == 'vcs':

        greeks_out = sg.get_greeks_4strategy_4date(alias=kwargs['alias'], as_of_date=date_to)
        ticker_portfolio = greeks_out['ticker_portfolio']

        if ticker_portfolio.empty:
            min_tr_dte = np.NaN
            result_output = {'success': False, 'net_oev': np.NaN, 'net_theta': np.NaN, 'long_short_ratio': np.NaN,
                         'recommendation': 'EMPTY', 'last_adjustment_days_ago': np.NaN,
                         'min_tr_dte': np.NaN, 'long_oev': np.NaN, 'short_oev': np.NaN, 'favQMove': np.NaN}
        else:
            min_tr_dte = min([exp.get_days2_expiration(ticker=x,date_to=date_to,instrument='options',con=con)['tr_dte'] for x in ticker_portfolio['ticker']])

            net_oev = ticker_portfolio['total_oev'].sum()
            net_theta = ticker_portfolio['theta'].sum()

            long_portfolio = ticker_portfolio[ticker_portfolio['total_oev'] > 0]
            short_portfolio = ticker_portfolio[ticker_portfolio['total_oev'] < 0]
            short_portfolio['total_oev']=abs(short_portfolio['total_oev'])

            long_oev = long_portfolio['total_oev'].sum()
            short_oev = short_portfolio['total_oev'].sum()

            if (not short_portfolio.empty) & (not long_portfolio.empty):
                long_short_ratio = 100*long_oev/short_oev

                long_portfolio.sort('total_oev', ascending=False, inplace=True)
                short_portfolio.sort('total_oev', ascending=False, inplace=True)

                long_ticker = long_portfolio['ticker'].iloc[0]
                short_ticker = short_portfolio['ticker'].iloc[0]

                long_contract_specs = cmi.get_contract_specs(long_ticker)
                short_contract_specs = cmi.get_contract_specs(short_ticker)

                if 12*long_contract_specs['ticker_year']+long_contract_specs['ticker_month_num'] < \
                                        12*short_contract_specs['ticker_year']+short_contract_specs['ticker_month_num']:
                    front_ticker = long_ticker
                    back_ticker = short_ticker
                    direction = 'long'
                else:
                    front_ticker = short_ticker
                    back_ticker = long_ticker
                    direction = 'short'

                if 'vcs_output' in kwargs.keys():
                    vcs_output = kwargs['vcs_output']
                else:
                    vcs_output = ovcs.generate_vcs_sheet_4date(date_to=date_to)

                vcs_pairs = vcs_output['vcs_pairs']
                selected_result = vcs_pairs[(vcs_pairs['ticker1'] == front_ticker) & (vcs_pairs['ticker2'] == back_ticker)]

                if selected_result.empty:
                    favQMove = np.NaN
                else:
                    current_Q = selected_result['Q'].iloc[0]
                    q_limit = of.get_vcs_filter_values(product_group=long_contract_specs['ticker_head'],
                                                   filter_type='tickerHead',direction=direction,indicator='Q')
                    if direction == 'long':
                        favQMove = current_Q-q_limit
                    elif direction == 'short':
                        favQMove = q_limit-current_Q
            else:
                long_short_ratio = np.NaN
                favQMove = np.NaN

            trades_frame = ts.get_trades_4strategy_alias(**kwargs)
            trades_frame_options = trades_frame[trades_frame['instrument'] == 'O']
            last_adjustment_days_ago = len(exp.get_bus_day_list(date_to=date_to,datetime_from=max(trades_frame_options['trade_date']).to_datetime()))

            if favQMove >= 10 and last_adjustment_days_ago > 10:
                recommendation = 'STOP-ratio normalized'
            elif min_tr_dte<25:
                recommendation = 'STOP-close to expiration'
            elif np.isnan(long_short_ratio):
                recommendation = 'STOP-not a proper calendar'
            else:
                if long_short_ratio < 80:
                    if favQMove < 0:
                        recommendation = 'buy_options_to_grow'
                    else:
                        recommendation = 'buy_options_to_shrink'
                elif long_short_ratio > 120:
                    if favQMove < 0:
                        recommendation = 'sell_options_to_grow'
                    else:
                        recommendation = 'sell_options_to_shrink'
                else:
                    recommendation = 'HOLD'

            result_output = {'success': True, 'net_oev': net_oev, 'net_theta': net_theta, 'long_short_ratio': long_short_ratio,
                         'recommendation': recommendation, 'last_adjustment_days_ago': last_adjustment_days_ago,
                         'min_tr_dte': min_tr_dte, 'long_oev': long_oev, 'short_oev': short_oev, 'favQMove': favQMove}

    else:
        result_output = {'success': False}

    if 'con' not in kwargs.keys():
        con.close()

    return result_output