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); } }