void CASCTrendStrategy::Test( entity::Quote* pQuote, CPortfolio* pPortfolio, boost::chrono::steady_clock::time_point& timestamp ) { // a mutex to protect from unexpected applying strategy settings concurrently boost::mutex::scoped_lock l(m_mut); //pQuote->set_last(2466); //pQuote->set_update_time("09:15:12"); CTechAnalyStrategy::Test(pQuote, pPortfolio, timestamp); if(!IsRunning()) return; if(!m_marketOpen) { string symbol = pQuote->symbol(); string quoteUpdateTime = pQuote->update_time(); bool isIF = isSymbolIF(symbol); string targetBeginTime = isIF ? IF_START_1 : NON_IF_START_1; if(quoteUpdateTime.compare(targetBeginTime) >= 0) { m_marketOpen = true; } else { return; } } string symbol = pQuote->symbol(); COHLCRecordSet* ohlc = GetRecordSet(symbol, m_period, timestamp); if(ohlc == NULL) return; int forceCloseBar = ohlc->GetSize() - m_forceCloseOffset; m_willRIndicatorSet->Calculate(ohlc); m_williamsR = m_willRIndicatorSet->GetRef(IND_WR, 0); m_watrStopIndSet->Calculate(ohlc); double trend = m_watrStopIndSet->GetRef(IND_WATR_TREND, 0); int currentBarIdx = ohlc->GetEndIndex(); if(ohlc->NbElements() > 1) { m_donchianHi = ohlc->HighSeries[currentBarIdx - 1]; m_donchianLo = ohlc->LowSeries[currentBarIdx - 1]; } else { m_donchianHi = DOUBLE_MAX_PRICE; m_donchianLo = DOUBLE_MIN_PRICE; } CPortfolioTrendOrderPlacer* pOrderPlacer = dynamic_cast<CPortfolioTrendOrderPlacer*>(pPortfolio->OrderPlacer()); if(pOrderPlacer->IsClosing()) { LOG_DEBUG(logger, boost::str(boost::format("[%s] ASC Trend - Check for modifying closing order") % pPortfolio->InvestorId())); pOrderPlacer->OnQuoteReceived(timestamp, pQuote); return; } if (pOrderPlacer->IsOpened()) { bool meetCloseCondition = false; bool forceClosing = IsForceClosing(); if(forceClosing // This close condition check is only effective on the bar after open || currentBarIdx >= forceCloseBar) { LOG_DEBUG(logger, boost::str(boost::format("[%s] ASC Trend - Portfolio(%s) Closing position due to Force close") % pPortfolio->InvestorId() % pPortfolio->ID())); ClosePosition(pPortfolio, pOrderPlacer, pQuote, "手动平仓"); return; } // check if the open bar is fake signal on next bar if(currentBarIdx == m_lastOpenBarIdx + 1 && !m_isRealSignal) { double preWR = m_willRIndicatorSet->GetRef(IND_WR, 1); m_isRealSignal = IsPreBarOpenCorrect(m_lastPositionOffset, preWR); LOG_DEBUG(logger, boost::str(boost::format("[%s] ASC Trend - Portfolio(%s) Check if pre bar open at fake signal - preWR: %.2f (%s)") % pPortfolio->InvestorId() % pPortfolio->ID() % preWR % GetPosiDirectionText(m_lastPositionOffset))); if(!m_isRealSignal) ClosePosition(pPortfolio, pOrderPlacer, pQuote, "假信号开仓立即平仓"); } unsigned int hour = 0, min = 0, sec = -1; if(ParseTimeString(pQuote->update_time(), &hour, &min, &sec)) //&& currentBarIdx > m_lastOpenBarIdx) { m_watr = m_watrStopIndSet->GetRef(IND_WATR_VAL, 0); m_stopPx = m_watrStopIndSet->GetRef(IND_WATR_STOP, 1); LOG_DEBUG(logger, boost::str(boost::format("[%s] ASC Trend - Portfolio(%s) Test for closing %s position - StopPx: %.2f, Last: %.2f, Ask: %.2f, Bid: %.2f") % pPortfolio->InvestorId() % pPortfolio->ID() % GetPosiDirectionText(m_lastPositionOffset) % m_stopPx % pQuote->last() % pQuote->ask() % pQuote->bid())); string chnCloseReason = "触发WATR止损(盈)"; bool meetCloseCondition = false; if(currentBarIdx > m_lastOpenBarIdx) { int barsSinceEntry = currentBarIdx - m_lastOpenBarIdx; if(barsSinceEntry == 1 && sec >= 58) // test when next 2 bars closing { m_stopPx = GetNearStopLoss(m_lastPositionOffset, ohlc, currentBarIdx - 1); meetCloseCondition = TestForClose(m_lastPositionOffset, pQuote, m_stopPx); if(meetCloseCondition) { LOG_DEBUG(logger, boost::str(boost::format("[%s] ASC Trend - Portfolio(%s) Closing position at next 1st bar. StopPx: %.2f") % pPortfolio->InvestorId() % pPortfolio->ID() % m_stopPx)); chnCloseReason = "开仓后第1根K线突破失败"; } } else if(barsSinceEntry == 2 && sec >= 58) { m_stopPx = GetNearStopLoss(m_lastPositionOffset, ohlc, currentBarIdx - 2); meetCloseCondition = TestForClose(m_lastPositionOffset, pQuote, m_stopPx); if(meetCloseCondition) { LOG_DEBUG(logger, boost::str(boost::format("[%s] ASC Trend - Portfolio(%s) Closing position at next 2nd bar. StopPx: %.2f") % pPortfolio->InvestorId() % pPortfolio->ID() % m_stopPx)); chnCloseReason = "开仓后第2根K线突破失败"; } if(!meetCloseCondition) { // if the 2nd bar after entry doesn't ever make new high/low, close it meetCloseCondition = IfNotBreakoutPreceding(pPortfolio, m_lastPositionOffset, ohlc, currentBarIdx); chnCloseReason = "开仓后第2根K线未创新高(低)"; } } else { meetCloseCondition = TestForClose(m_lastPositionOffset, pQuote, m_stopPx); } } else // still the bar opening the position { double initStopPx = m_stopPx; double lastTrend = m_watrStopIndSet->GetRef(IND_WATR_TREND, 1); // in case opened position is different than trend of last bar use current bar's stopPx if((m_lastPositionOffset == entity::LONG && lastTrend < 0) || (m_lastPositionOffset == entity::SHORT && lastTrend > 0)) { if(m_initStopPx > 0) // when m_initStopPx was given proper value { LOG_DEBUG(logger, boost::str(boost::format("[%s] ASC Trend - Portfolio(%s) Using init stopPx : %.3f") % pPortfolio->InvestorId() % pPortfolio->ID() % m_initStopPx)); initStopPx = m_initStopPx; } } meetCloseCondition = TestForClose(m_lastPositionOffset, pQuote, initStopPx); } if(meetCloseCondition) { LOG_DEBUG(logger, boost::str(boost::format("[%s] ASC Trend - Portfolio(%s) Closing position due to WATR stop") % pPortfolio->InvestorId() % pPortfolio->ID())); ClosePosition(pPortfolio, pOrderPlacer, pQuote, chnCloseReason.c_str()); m_lastCloseBarIdx = currentBarIdx; return; } } return; // don't need to go to test open trigger any more } // Testing for Open position double last = pQuote->last(); LOG_DEBUG(logger, boost::str(boost::format("[%s] ASC Trend - Portfolio(%s) Testing for OPEN - Last: %.2f, WR: %.2f, Hi: %.2f, Lo: %.2f") % pPortfolio->InvestorId() % pPortfolio->ID() % last % m_williamsR % m_donchianHi % m_donchianLo)); entity::PosiDirectionType direction = TestForOpen(pQuote, m_williamsR, m_donchianHi, m_donchianLo, trend); if(currentBarIdx < forceCloseBar && direction > entity::NET && (currentBarIdx > m_lastCloseBarIdx)) // In general, don't open position at the bar just closing position //|| direction != m_lastPositionOffset)) // unless the direction is different { if(!pOrderPlacer->IsWorking()) { LOG_DEBUG(logger, boost::str(boost::format("[%s] ASC Trend - Portfolio(%s) Opening position at bar %d") % pPortfolio->InvestorId() % pPortfolio->ID() % currentBarIdx )); OpenPosition(direction, pOrderPlacer, pQuote, timestamp, false, boost::str(boost::format("WR(%.2f)满足条件") % m_williamsR).c_str()); m_lastOpenBarIdx = currentBarIdx; // The stopPx at the current bar in this moment will be initial stop price as backup stop price. // in case the preceding trend is different than this one, this initial stop price will be effective. m_initStopPx = m_watrStopIndSet->GetRef(IND_WATR_STOP, 0); return; } } }
BOOL CMorphaResDlg::OnInitDialog() { CPropertyPage::OnInitDialog(); CMainFrame* pMainFrm=(CMainFrame*)AfxGetMainWnd(); CMorphaDataRetriveDlg& dlg = *(pMainFrm->m_pWndMorphadlg); CString strSQLCRMfi("select morpharesult.* into morphafordisplay \ from morpharesult,basicinfo,morphaimage,spermchait,morpharesultratio \ where morpharesult.pdetectno = basicinfo.pdetectno \ and morpharesult.pdetectno = morphaimage.pdetectno \ and morpharesult.pdetectno = spermchait.pdetectno \ and morpharesult.pdetectno = morpharesultratio.pdetectno"); try { if(IsTableExist(theConnection, "morphafordisplay") == true) { theConnection->Execute((LPCTSTR)"drop table morphafordisplay",NULL,adCmdText); } theConnection->Execute((LPCTSTR)strSQLCRMfi,NULL,adCmdText); CString strGetN("select count(*) from morphafordisplay"); _RecordsetPtr rs=theConnection->Execute((LPCSTR)strGetN,NULL,adCmdText); dlg.m_dp[0].nCurPage = 1; dlg.m_dp[0].nTotalRecord=rs->GetCollect((long)0).iVal; dlg.m_dp[0].nPageRecord = NUMPERPAGE; dlg.m_dp[0].nTotalPage = dlg.m_dp[0].nTotalRecord / dlg.m_dp[0].nPageRecord + (dlg.m_dp[0].nTotalRecord % dlg.m_dp[0].nPageRecord!=0); CString queryinfo; queryinfo.Format("共查询到%d条记录",dlg.m_dp[0].nTotalRecord); dlg.SetDlgItemText(IDC_STATIC_QUERY,queryinfo); if(dlg.m_dp[0].nTotalRecord == 0 ) { CMainFrame* pMainFrm=(CMainFrame*)AfxGetMainWnd(); pMainFrm->m_pWndMorphadlg->GetDlgItem(IDC_BTN_FIRSTPAGE)->EnableWindow(FALSE); pMainFrm->m_pWndMorphadlg->GetDlgItem(IDC_BTN_PREPAGE)->EnableWindow(FALSE); pMainFrm->m_pWndMorphadlg->GetDlgItem(IDC_BTN_NEXTPAGE)->EnableWindow(FALSE); pMainFrm->m_pWndMorphadlg->GetDlgItem(IDC_BTN_LASTPAGE)->EnableWindow(FALSE); pMainFrm->m_pWndMorphadlg->GetDlgItem(IDC_PAGENUM)->EnableWindow(FALSE); return FALSE; } int lowRow, upRow; dlg.GetPageBound(1,lowRow,upRow,dlg.m_dp[0]); GetRecordSet(rs,lowRow,upRow); int n=dlg.m_resdlg.m_wndMorphaDataList.SetData(rs); queryinfo.Format("第 %d / %d 页",dlg.m_dp[0].nCurPage,dlg.m_dp[0].nTotalPage); dlg.SetDlgItemText(IDC_PAGENUM,queryinfo); dlg.GetDlgItem(IDC_BTN_FIRSTPAGE)->EnableWindow(dlg.m_dp[dlg.IsInqueryState()].nCurPage != 1); dlg.GetDlgItem(IDC_BTN_PREPAGE)->EnableWindow(dlg.m_dp[dlg.IsInqueryState()].nCurPage != 1); dlg.GetDlgItem(IDC_BTN_NEXTPAGE)->EnableWindow(dlg.m_dp[dlg.IsInqueryState()].nCurPage != dlg.m_dp[dlg.IsInqueryState()].nTotalPage); dlg.GetDlgItem(IDC_BTN_LASTPAGE)->EnableWindow(dlg.m_dp[dlg.IsInqueryState()].nCurPage != dlg.m_dp[dlg.IsInqueryState()].nTotalPage ); } catch (_com_error& e) { MessageBox(e.Description()); return FALSE; } return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE }
void CRangeTrendStrategy::Test( entity::Quote* pQuote, CPortfolio* pPortfolio, boost::chrono::steady_clock::time_point& timestamp ) { // a mutex to protect from unexpected applying strategy settings concurrently boost::mutex::scoped_lock l(m_mut); //pQuote->set_last(2466); //pQuote->set_update_time("09:15:12"); CTechAnalyStrategy::Test(pQuote, pPortfolio, timestamp); if(!IsRunning()) return; if(!m_marketOpen) { string symbol = pQuote->symbol(); string quoteUpdateTime = pQuote->update_time(); bool isIF = isSymbolIF(symbol); string targetBeginTime = isIF ? IF_START_1 : NON_IF_START_1; if(quoteUpdateTime.compare(targetBeginTime) >= 0) { m_marketOpen = true; } else { return; } } string symbol = pQuote->symbol(); COHLCRecordSet* ohlc = GetRecordSet(symbol, m_timeFrame, timestamp); if(ohlc == NULL) return; int forceCloseBar = ohlc->GetSize() - m_forceCloseOffset; int currentBarIdx = ohlc->GetEndIndex(); if(currentBarIdx <= m_openPeriod) return; // too few bars to test m_openDonchianDataSet->Calculate(ohlc); if(m_openDonchianDataSet->AvailableElems() > 1) { m_upperBoundOpen = m_openDonchianDataSet->GetRef(IND_DONCHIAN_Hi, 1); m_lowerBoundOpen = m_openDonchianDataSet->GetRef(IND_DONCHIAN_Lo, 1); } m_closeDonchianDataSet->Calculate(ohlc); if(m_closeDonchianDataSet->AvailableElems() > 1) { m_upperBoundClose = m_closeDonchianDataSet->GetRef(IND_DONCHIAN_Hi, 1); m_lowerBoundClose = m_closeDonchianDataSet->GetRef(IND_DONCHIAN_Lo, 1); } m_atrDataSet->Calculate(ohlc); m_NATR = m_atrDataSet->GetRef(IND_ATR, 1); if(currentBarIdx > m_lastBarIdx) // Get into next bar { m_lastBarIdx = currentBarIdx; if(m_pendingOrdCmd.get() != NULL) { if(m_pendingOrdCmd->IsActive()) { // Fire command if(m_pendingOrdCmd->GetOffset() == entity::OPEN) // For Open position command { m_lastPosiDirection = m_pendingOrdCmd->GetDirection(); m_lastCostPx = m_pendingOrdCmd->Fire(pQuote, pPortfolio, timestamp); m_StopLoss = m_stopLossFactor * m_NATR; LOG_DEBUG(logger, boost::str(boost::format("Fired StrategyOrderCommand(OPEN). LastCost: %.2f, StopLoss: %.2f at %s") % m_lastCostPx % m_StopLoss % pQuote->update_time())); } else // for close position command { // reset flags double closePx = m_pendingOrdCmd->Fire(pQuote, pPortfolio, timestamp); LOG_DEBUG(logger, boost::str(boost::format("Fired StrategyOrderCommand(CLOSE). ClosePx: %.2f at %s") % closePx % pQuote->update_time())); m_lastPosiDirection = entity::NET; m_lastCostPx = -1.0; m_StopLoss = 0; m_trending = false; } if(!m_pendingOrdCmd->IsActive()) // command reverted will not be reset { LOG_DEBUG(logger, boost::str(boost::format("StrategyOrderCommand gets inactive, and removed."))); m_pendingOrdCmd.reset(); } return; } else { LOG_DEBUG(logger, boost::str(boost::format("StrategyOrderCommand is inactive, and gets removed."))); m_pendingOrdCmd.reset(); } } } else // Still the current bar { if(m_pendingOrdCmd.get() != NULL) { if(m_pendingOrdCmd->GetRevertOnClose() && m_pendingOrdCmd->GetOffset() == entity::OPEN) { // ONLY for revert Open position after close m_trending = true; m_lastPosiDirection = m_pendingOrdCmd->GetDirection(); m_lastCostPx = m_pendingOrdCmd->Fire(pQuote, pPortfolio, timestamp); m_StopLoss = m_stopLossFactor * m_NATR; LOG_DEBUG(logger, boost::str(boost::format("Fired StrategyOrderCommand(Revert-OPEN). LastCost: %.2f, StopLoss: %.2f at %s") % m_lastCostPx % m_StopLoss % pQuote->update_time())); m_pendingOrdCmd.reset(); } } } CPortfolioTrendOrderPlacer* pOrderPlacer = dynamic_cast<CPortfolioTrendOrderPlacer*>(pPortfolio->OrderPlacer()); if(pOrderPlacer->IsClosing()) { LOG_DEBUG(logger, boost::str(boost::format("[%s] Range Trend - Check for modifying closing order") % pPortfolio->InvestorId())); pOrderPlacer->OnQuoteReceived(timestamp, pQuote); return; } unsigned int hour = 0, min = 0, sec = -1; if(!ParseTimeString(pQuote->update_time(), &hour, &min, &sec)) return; int secInBar = (min * 60 + sec) % m_timeFrame; bool isTestingBar = secInBar > m_timeFrame - 5; if(!isTestingBar) return; // Testing for Close Position if (pOrderPlacer->IsOpened()) { bool meetCloseCondition = false; bool forceClosing = IsForceClosing(); if(forceClosing // This close condition check is only effective on the bar after open || currentBarIdx >= forceCloseBar) { LOG_DEBUG(logger, boost::str(boost::format("[%s] Range Trend - Portfolio(%s) Closing position due to Force close") % pPortfolio->InvestorId() % pPortfolio->ID())); CStrategyOrderCommand forceCloseCommand(entity::CLOSE, pOrderPlacer, this); forceCloseCommand.SetNote( forceClosing ? "手动平仓" : "收市前平仓"); double px = forceCloseCommand.Fire(pQuote, pPortfolio, timestamp); return; } // Stop Gain & Stop Loss string closeComment; bool revertOffset = false; bool closePosition = TestForClose(pPortfolio, pQuote, m_upperBoundClose, m_lowerBoundClose, &closeComment, &revertOffset); if(closePosition) { if(m_pendingOrdCmd.get() == NULL) { m_pendingOrdCmd = OrderCommandPtr(new CStrategyOrderCommand(entity::CLOSE, pOrderPlacer, this)); m_pendingOrdCmd->SetNote(closeComment); m_pendingOrdCmd->SetRevertOnClose(revertOffset); m_pendingOrdCmd->Activate(); } else { if(!m_pendingOrdCmd->IsActive()) { m_pendingOrdCmd->SetNote(closeComment); m_pendingOrdCmd->SetRevertOnClose(revertOffset); m_pendingOrdCmd->Activate(); } } } else { if(m_pendingOrdCmd.get() != NULL) m_pendingOrdCmd->Deactivate(); } } // Testing for Open position else if (currentBarIdx < forceCloseBar) { string openComment; entity::PosiDirectionType direction = TestForOpen(pPortfolio, pQuote, m_upperBoundOpen, m_lowerBoundOpen, &openComment); if(direction > entity::NET) { if(m_pendingOrdCmd.get() == NULL) { m_pendingOrdCmd = OrderCommandPtr(new CStrategyOrderCommand(entity::OPEN, pOrderPlacer, this)); m_pendingOrdCmd->SetDirection(direction); m_pendingOrdCmd->SetNote(openComment); m_pendingOrdCmd->Activate(); } else{ m_pendingOrdCmd->SetDirection(direction); m_pendingOrdCmd->SetNote(openComment); if(!m_pendingOrdCmd->IsActive()) { m_pendingOrdCmd->Activate(); } } } else { if(m_pendingOrdCmd.get() != NULL) m_pendingOrdCmd->Deactivate(); } } }