Ejemplo n.º 1
0
void Strategy::HandleRHTrading( const ou::tf::Quote& quote ) {

  // add trades to chart
  // add based upon confirmed price

  if ( quote.IsValid() ) {

    m_dtQuote = quote.DateTime();

    double mid = quote.Midpoint();

    m_pOrdersOutstandingLongs->HandleQuote( quote );
    m_pOrdersOutstandingShorts->HandleQuote( quote );

    unsigned int cntLongs = m_pOrdersOutstandingLongs->GetCountOfOutstandingMatches();
    m_ceCountLongs.Append( m_dtQuote, cntLongs );
    unsigned int cntShorts = m_pOrdersOutstandingShorts->GetCountOfOutstandingMatches();
    m_ceCountShorts.Append( m_dtQuote, cntShorts );
    unsigned int dif = ( cntLongs > cntShorts ) ? cntLongs - cntShorts : cntShorts - cntLongs;

//    m_ceOutstandingExitsLong.Add( dt, cntLongs + m_pOrdersOutstandingLongs->GetCountOfOutstandingEntries() );
//    m_ceOutstandingExitsShort.Add( dt, cntShorts + m_pOrdersOutstandingShorts->GetCountOfOutstandingEntries() );

    infoBollinger& info( m_vInfoBollinger[ 0 ] );

    // since slope is delayed, check that data confirms slope before initiating actual trade
    // also, width of bollinger can limit when trades occur
    // track maximum, minimum, average width?

    ETradingState eTradingState( eTSUnknown );
    if ( 0.0 < info.m_statsSlope.Slope() ) {
      if ( mid > info.m_ema.Ago( 0 ).Value() ) {
        eTradingState = eTSSlopeRisingAboveMean;
      }
      else {
        if ( mid < info.m_ema.Ago( 0 ).Value() ) {
          eTradingState = eTSSlopeRisingBelowMean;
        }
      }
    }
    else {
      if ( 0.0 > info.m_statsSlope.Slope() ) {
        if ( mid < info.m_ema.Ago( 0 ).Value() ) {
          eTradingState = eTSSlopeFallingBelowMean;
        }
        else {
          if ( mid > info.m_ema.Ago( 0 ).Value() ) {
            eTradingState = eTSSlopeFallingAboveMean;
          }
        }
      }
    }

    if ( m_eTradingState != eTradingState ) {
      //std::cout << "Trading state " << eTradingState << std::endl;
      m_vTradeStateHistory.push_back( TradeStateHistory( eTradingState, quote ) );
      //m_eTradingState = eTradingState;

      size_t ix( m_vTradeStateHistory.size() );
      if ( 3 <= ix ) {
        TradeStateHistorySummary& 
          ths( m_mxTradeStateHistorySummary
                  [ m_vTradeStateHistory[ ix - 3 ].eTradingState ]
                  [ m_vTradeStateHistory[ ix - 2 ].eTradingState ]
                  [ m_vTradeStateHistory[ ix - 1 ].eTradingState ]
          );
        ou::tf::Quote& quote1( m_vTradeStateHistory[ ix - 2 ].quote );
        ou::tf::Quote& quote2( m_vTradeStateHistory[ ix - 1 ].quote );
        if ( quote2.Bid() > quote1.Ask() ) { // profitable long
          ++ths.nLongs;
          ths.dblTotalLongs += quote2.Bid() - quote1.Ask();
        }
        if ( quote1.Ask() > quote2.Bid() ) { // profitable short
          ++ths.nShorts;
          ths.dblTotalShorts += quote1.Ask() - quote2.Bid();
        }
        ths.dblSpread = quote.Spread();
        ths.dblBollingerWidth = info.m_stats.BBUpper() - info.m_stats.BBLower();
      }
    }

    // todo:
    // C:\Data\Resources\Books\Moving_Averages Kennedy
    // style 1: moving average compression - search for it, then use it set up option 
    // style 2: sma1 > sma2 > sma3 > sma4
    // 

    if ( m_bTrade ) {
      /*
      // scalping based upon acceleration crossing
      double dblNormalizedPrice;
      ou::tf::Order::pOrder_t pOrder;
      ou::tf::Instrument::pInstrument_t pInstrument;
      switch ( info.m_stateAccel.State() ) {
      case ou::tf::Crossing<double>::EGTX: 
        m_pOrdersOutstandingLongs->CancelAllButNEntryOrders( 2 );
        pInstrument = m_pPositionLongs->GetInstrument();
        dblNormalizedPrice = pInstrument->NormalizeOrderPrice( quote.Midpoint() );  // -0.10? +0.10?
        pOrder = m_pPositionLongs->ConstructOrder( ou::tf::OrderType::Limit, ou::tf::OrderSide::Buy, 1, dblNormalizedPrice );
        pOrder->OnOrderFilled.Add( MakeDelegate( this, &Strategy::HandleOrderFilled ) );
        pOrder->SetDescription( "Info[0].Long" );
        m_pOrdersOutstandingLongs->AddOrderFilling( 
          new ou::tf::OrdersOutstanding::structRoundTrip( 
            pOrder, 
            dblNormalizedPrice + info.m_dblBollingerWidth, // profit point, but let it accumulate with trailing stop
            dblNormalizedPrice - 0.5 * info.m_dblBollingerWidth )  // stop  ... between the two, trail while in progress, parabolic while not in progress
          );
        m_pPositionLongs->PlaceOrder( pOrder );
        //++m_nUpTransitions;
        break;
      case ou::tf::Crossing<double>::ELTX: 
        m_pOrdersOutstandingShorts->CancelAllButNEntryOrders( 2 );
        pInstrument = m_pPositionShorts->GetInstrument();
        dblNormalizedPrice = pInstrument->NormalizeOrderPrice( quote.Midpoint() );  // -0.10? +0.10?
        pOrder = m_pPositionShorts->ConstructOrder( ou::tf::OrderType::Limit, ou::tf::OrderSide::Sell, 1, dblNormalizedPrice );
        pOrder->OnOrderFilled.Add( MakeDelegate( this, &Strategy::HandleOrderFilled ) );
        pOrder->SetDescription( "Info[0].Short" );
        m_pOrdersOutstandingShorts->AddOrderFilling( 
          new ou::tf::OrdersOutstanding::structRoundTrip( 
            pOrder, 
            dblNormalizedPrice - info.m_dblBollingerWidth, // profit point, but let it accumulate with trailing stop
            dblNormalizedPrice + 0.5 * info.m_dblBollingerWidth )  // stop  ... between the two, trail while in progress, parabolic while not in progress
          );
        m_pPositionShorts->PlaceOrder( pOrder );
        //++m_nDnTransitions;
        break;
      }
      */

      // strong rising indicator
      bool bRising = 
           ( m_vInfoBollinger[0].m_statsSlope.MeanY() > m_vInfoBollinger[1].m_statsSlope.MeanY() ) // various slopes are greater than the next longer term
        && ( m_vInfoBollinger[1].m_statsSlope.MeanY() > m_vInfoBollinger[2].m_statsSlope.MeanY() )
        && ( m_vInfoBollinger[2].m_statsSlope.MeanY() > m_vInfoBollinger[3].m_statsSlope.MeanY() )
        && ( 0 < m_vInfoBollinger[3].m_statsSlope.MeanY() )
        ;
    
      bool bFalling = 
           ( m_vInfoBollinger[0].m_statsSlope.MeanY() < m_vInfoBollinger[1].m_statsSlope.MeanY() ) // various slopes are greater than the next longer term
        && ( m_vInfoBollinger[1].m_statsSlope.MeanY() < m_vInfoBollinger[2].m_statsSlope.MeanY() )
        && ( m_vInfoBollinger[2].m_statsSlope.MeanY() < m_vInfoBollinger[3].m_statsSlope.MeanY() )
        && ( 0 > m_vInfoBollinger[3].m_statsSlope.MeanY() )
        ;

      switch ( m_eInd1 ) {
      case eInd1WaitForEntry:
        if ( bRising ) {
          m_pOrderTrending = m_pPositionLongs->ConstructOrder( ou::tf::OrderType::Market, ou::tf::OrderSide::Buy, 1 );
          m_pOrderTrending->OnOrderFilled.Add( MakeDelegate( this, &Strategy::HandleOrderFilled ) );
          m_pOrderTrending->SetDescription( "Ind1 Long" );
          m_pPositionLongs->PlaceOrder( m_pOrderTrending );
          m_eInd1 = eInd1InRising;
        }
        else {
          if ( bFalling ) {
            m_pOrderTrending = m_pPositionShorts->ConstructOrder( ou::tf::OrderType::Market, ou::tf::OrderSide::Sell, 1 );
            m_pOrderTrending->OnOrderFilled.Add( MakeDelegate( this, &Strategy::HandleOrderFilled ) );
            m_pOrderTrending->SetDescription( "Ind1 Short" );
            m_pPositionShorts->PlaceOrder( m_pOrderTrending );
            m_eInd1 = eInd1InFalling;
          }
        }
        break;
      case eInd1InRising:
        if ( !bRising ) {
          m_dblStop = ( mid - m_pOrderTrending->GetAverageFillPrice() ) / 2.0;
          m_eInd1 = eInd1FollowLongStop;
        }
        break;
      case eInd1InFalling:
        if ( !bFalling ) {
          m_dblStop = ( m_pOrderTrending->GetAverageFillPrice() - mid ) / 2.0;
          m_eInd1 = eINd1FollowShortStop;
        }
        break;
      case eInd1FollowLongStop:
        if ( bRising ) {
          m_eInd1 = eInd1InRising;
        }
        else {
          if ( mid < m_dblStop ) {
            m_pOrderTrending = m_pPositionLongs->ConstructOrder( ou::tf::OrderType::Market, ou::tf::OrderSide::Sell, 1 );
            m_pOrderTrending->OnOrderFilled.Add( MakeDelegate( this, &Strategy::HandleOrderFilled ) );
            m_pOrderTrending->SetDescription( "Ind1 Long Exit" );
            m_pPositionLongs->PlaceOrder( m_pOrderTrending );
            m_eInd1 = eInd1WaitForEntry;
          }
        }
        break;
      case eINd1FollowShortStop:
        if ( bFalling ) {
          m_eInd1 = eInd1InFalling;
        }
        else {
          if ( mid > m_dblStop ) {
            m_pOrderTrending = m_pPositionShorts->ConstructOrder( ou::tf::OrderType::Market, ou::tf::OrderSide::Buy, 1 );
            m_pOrderTrending->OnOrderFilled.Add( MakeDelegate( this, &Strategy::HandleOrderFilled ) );
            m_pOrderTrending->SetDescription( "Ind1 Short Exit" );
            m_pPositionShorts->PlaceOrder( m_pOrderTrending );
            m_eInd1 = eInd1InFalling;
          }
        }
        break;
      }

      double dblUnrealized;
      double dblRealized;
      double dblCommission;
      double dblTotal;
//      m_pPortfolio->QueryStats( dblUnrealized, dblRealized, dblCommission, dblTotal );
//      m_cePL.Append( m_dtQuote, dblTotal );

    }

    m_eTradingState = eTradingState;
/*
    if ( m_bTrade ) {
      switch ( m_eTradingState ) {
      case eTSUnknown:
        break;
      case eTSSlopeRisingAboveMean:
        switch ( eTradingState ) {
        case eTSSlopeRisingBelowMean:
          TakeLongProfits();
          GoShort();
          break;
        }
        break;
      case eTSSlopeRisingBelowMean:
        break;
      case eTSSlopeFallingAboveMean:
        break;
      case eTSSlopeFallingBelowMean:
        switch ( eTradingState ) {
        case eTSSlopeFallingAboveMean:
          TakeShortProfits();
          GoLong();
          break;
        }
        break;
      }
*/
/*
    switch ( m_eBollinger1EmaSlope ) {
    case eSlopeUnknown:
      if ( 0.0 < info.m_statsSlope.Slope() ) {
        std::cout << dt << "Starting with a long" << std::endl;
        GoLong();
        m_eBollinger1EmaSlope = eSlopePos;
      }
      else {
        if ( 0.0 > info.m_statsSlope.Slope() ) {
          std::cout << dt << "Starting with a short" << std::endl;
          GoShort();
          m_eBollinger1EmaSlope = eSlopeNeg;
        }
      }
      break;
    case eSlopeNeg:
      if ( 0.0 < info.m_statsSlope.Slope() ) {
        std::cout << dt << "Reversing Short to Long" << std::endl;
        m_pPosition->ClosePosition();
        GoLong();
        m_eBollinger1EmaSlope = eSlopePos;
      }
      break;
    case eSlopePos:
      if ( 0.0 > info.m_statsSlope.Slope() ) {
        std::cout << dt << "Reversing Long to Short" << std::endl;
        m_pPosition->ClosePosition();
        GoShort();
        m_eBollinger1EmaSlope = eSlopeNeg;
      }
      
      break;
    }
    */

  }
}
    void InterpolatedYoYOptionletStripper<Interpolator1D>::
    initialize(const boost::shared_ptr<YoYCapFloorTermPriceSurface> &s,
               const boost::shared_ptr<YoYInflationCapFloorEngine> &p,
               const Real slope) const {
        YoYCapFloorTermPriceSurface_ = s;
        p_ = p;
        lag_ = YoYCapFloorTermPriceSurface_->observationLag();
        frequency_ = YoYCapFloorTermPriceSurface_->frequency();
        indexIsInterpolated_ = YoYCapFloorTermPriceSurface_->indexIsInterpolated();
        Natural fixingDays_ = YoYCapFloorTermPriceSurface_->fixingDays();
        Natural settlementDays = 0; // always
        Calendar cal = YoYCapFloorTermPriceSurface_->calendar();
        BusinessDayConvention bdc =
            YoYCapFloorTermPriceSurface_->businessDayConvention();
        DayCounter dc = YoYCapFloorTermPriceSurface_->dayCounter();

        // switch from caps to floors when out of floors
        Rate maxFloor = YoYCapFloorTermPriceSurface_->floorStrikes().back();
        YoYInflationCapFloor::Type useType = YoYInflationCapFloor::Floor;
        Period TPmin = YoYCapFloorTermPriceSurface_->maturities().front();
        // create a "fake index" based on Generic, this should work
        // provided that the lag and frequency are correct
        RelinkableHandle<YoYInflationTermStructure> hYoY(
                                       YoYCapFloorTermPriceSurface_->YoYTS());
        boost::shared_ptr<YoYInflationIndex> anIndex(
                                           new YYGenericCPI(frequency_, false,
                                                            false, lag_,
                                                            Currency(), hYoY));

        // strip each K separatly
        for (Size i=0; i<YoYCapFloorTermPriceSurface_->strikes().size(); i++) {
            Rate K = YoYCapFloorTermPriceSurface_->strikes()[i];
            if (K > maxFloor) useType = YoYInflationCapFloor::Cap;

            // solve for the initial point on the vol curve
            Brent solver;
            Real solverTolerance_ = 1e-7;
             // these are VOLATILITY guesses (always +)
            Real lo = 0.00001, hi = 0.08;
            Real guess = (hi+lo)/2.0;
            Real found;
            Real priceToMatch =
                (useType == YoYInflationCapFloor::Cap ?
                 YoYCapFloorTermPriceSurface_->capPrice(TPmin, K) :
                 YoYCapFloorTermPriceSurface_->floorPrice(TPmin, K));

            try{
                found = solver.solve(
                      ObjectiveFunction(useType, slope, K, lag_, fixingDays_,
                                        anIndex, YoYCapFloorTermPriceSurface_,
                                        p_, priceToMatch),
                      solverTolerance_, guess, lo, hi );
            } catch( std::exception &e) {
                QL_FAIL("failed to find solution here because: " << e.what());
            }

            // ***create helpers***
            Real notional = 10000; // work in bps
            std::vector<boost::shared_ptr<BootstrapHelper<YoYOptionletVolatilitySurface> > > helperInstruments;
            std::vector<boost::shared_ptr<YoYOptionletHelper> > helpers;
            for (Size j = 0; j < YoYCapFloorTermPriceSurface_->maturities().size(); j++){
                Period Tp = YoYCapFloorTermPriceSurface_->maturities()[j];

                Real nextPrice =
                    (useType == YoYInflationCapFloor::Cap ?
                     YoYCapFloorTermPriceSurface_->capPrice(Tp, K) :
                     YoYCapFloorTermPriceSurface_->floorPrice(Tp, K));

                Handle<Quote> quote1(boost::shared_ptr<Quote>(
                                               new SimpleQuote( nextPrice )));
                // helper should be an integer number of periods away,
                // this is enforced by rounding
                Size nT = (Size)floor(s->timeFromReference(s->yoyOptionDateFromTenor(Tp))+0.5);
                helpers.push_back(boost::shared_ptr<YoYOptionletHelper>(
                          new YoYOptionletHelper(quote1, notional, useType,
                                                 lag_,
                                                 dc, cal,
                                                 fixingDays_,
                                                 anIndex, K, nT, p_)));

                boost::shared_ptr<ConstantYoYOptionletVolatility> yoyVolBLACK(
                          new ConstantYoYOptionletVolatility(found, settlementDays,
                                                             cal, bdc, dc,
                                                             lag_, frequency_,
                                                             false,
                                                             // -100% to +300%
                                                             -1.0,3.0));

                helpers[j]->setTermStructure(
                       // gets underlying pointer & removes const
                       const_cast<ConstantYoYOptionletVolatility*>(
                                                          yoyVolBLACK.get()));
                helperInstruments.push_back(helpers[j]);
            }
            // ***bootstrap***
            // this is the artificial vol at zero so that first section works
            Real Tmin = s->timeFromReference(s->yoyOptionDateFromTenor(TPmin));
            Volatility baseYoYVolatility = found - slope * Tmin * found;
            Rate eps = std::max(K, 0.02) / 1000.0;
            Rate minStrike = K-eps;
            Rate maxStrike = K+eps;
            boost::shared_ptr<
                PiecewiseYoYOptionletVolatilityCurve<Interpolator1D> > testPW(
                new PiecewiseYoYOptionletVolatilityCurve<Interpolator1D>(
                                            settlementDays, cal, bdc, dc, lag_,
                                            frequency_, indexIsInterpolated_,
                                            minStrike, maxStrike,
                                            baseYoYVolatility,
                                            helperInstruments) );
            testPW->recalculate();
            volCurves_.push_back(testPW);
        }
    }