⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chartma.cpp

📁 类似于股市K线技术分析的系统源码
💻 CPP
字号:
// ChartMA.cpp: implementation of the CChartMA class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "LastProject.h"
#include "ChartMA.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CChartMA::CChartMA(CRecords *pRecords,CDirectFace * pFace,int P1,int P2,int P3)
{
	int nWidth = pFace->m_rect.Width() - 60;
	int nHeight = pFace->m_rect.Height() - 50;
	int Zero = pFace->m_rect.Height() - 20;
	double max = 0,min = 9999;
//*******************
	CDatabase db;
	CRecordset	rs;
	CString VAL,SQL;
	SQL.Format("SELECT * FROM ExchangeType WHERE ETypeCode='%s' ",pRecords->ExCode);
	try
	{
		db.OpenEx(DEFAULTDSN,CDatabase::noOdbcDialog);
		rs.m_pDatabase = &db;
		rs.Open(AFX_DB_USE_DEFAULT_TYPE,SQL);
		//读取分析数据
		while(!rs.IsEOF())
		{
			rs.GetFieldValue("ChineseName",VAL);
			rs.MoveNext();
		}
	}catch(CDBException *e)
	{
		e->ReportError();
	}
	if(rs.IsOpen())	rs.Close();
	if(db.IsOpen()) db.Close();



//*******************	
	//计算所画区域中的最大最小值
	for(int i = pRecords->m_records.size()-1;i>=0;i--)
	{
		if(nWidth<8) break;
		if(pRecords->m_records.at(i).max>max) max = pRecords->m_records.at(i).max;
		if(pRecords->m_records.at(i).min<min) min = pRecords->m_records.at(i).min;
		nWidth -= 10;
	}
	nWidth = pFace->m_rect.Width() - 60;
	if(max==min) 
	{
		max = min * 1.4;
		min = min * 0.8;
	}
	double delta = max - min;
	CString st;
	st.Format ("nHeight=%d,nWidth=%d,delta=%4.4f",nHeight,nWidth,delta);
	//AfxMessageBox(st);

	CString fmt,str;
	HDC layer = NULL;
	pFace->m_lpLayer[1]->GetDC(&layer);
	CDC *pDC = CDC::FromHandle(layer);
	pDC->SetBkColor(RGB(0,0,0));
	pDC->SetTextColor(RGB(0,170,0));
	
	//刷清图层
	pDC->SelectObject(::GetStockObject(BLACK_BRUSH));
	pDC->SelectObject(&pFace->m_FramePen);
	pDC->Rectangle(0,0,pFace->m_rect.Width(),pFace->m_rect.Height());

	//画题头部分
	pDC->SelectObject(&pFace->m_TitleFont);
	//pDC->TextOut(5,8,CodeToName(pRecords->ExCode));
	pDC->TextOut(5,8,VAL);
	pDC->TextOut(100,8,pRecords->TableName);
	pDC->SetTextColor(RGB(255,0,0));
	str.Format("MA%3d",P1);
	if(P1==0) pDC->TextOut(140,8,"MA");else pDC->TextOut(140,8,str);
	pDC->SetTextColor(RGB(0,255,0));
	str.Format("MA%3d",P2);
	if(P1==0) pDC->TextOut(180,8,"MA");else pDC->TextOut(180,8,str);
	pDC->SetTextColor(RGB(255,255,0));
	str.Format("MA%3d",P3);
	if(P1==0) pDC->TextOut(220,8,"MA");else pDC->TextOut(220,8,str);


	pDC->SetTextColor(RGB(0,170,0));
	//画坐标轴
	pDC->SelectObject(&pFace->m_WhitePen);
	pDC->MoveTo(3,Zero);
	pDC->LineTo(nWidth+5,Zero);
	pDC->LineTo(nWidth+5,30);

	int lab = 0;

	//画平行于X轴网格
	pDC->SelectObject(&pFace->m_GrayPen);
	pDC->SelectObject(&pFace->m_YFont);
	if(pRecords->ExCode.Find("27")==-1) fmt = "%.4lf";else fmt = "%.2lf";
	for(i = 0;i<=8;i++)
	{
		int y = (int)(nHeight * i / 8);
		str.Format(fmt,min + delta * i / 8); 
		pDC->TextOut(nWidth+8,Zero-y-6,str);
		if(i==0) continue;
		pDC->MoveTo(3,Zero - y);
		pDC->LineTo(nWidth+5,Zero - y);	
	}

	//画柱状图
	pDC->SelectObject(&pFace->m_XFont);
	for(i = pRecords->m_records.size()-1;i>=0;i--)
	{
		if(nWidth<8) break;
		double close = Zero - (pRecords->m_records.at(i).close-min) * nHeight / (delta);//Zero - (pRecords->m_records.at(i).close-min) * nHeight / (delta);
		double open = Zero - (pRecords->m_records.at(i).open-min) * nHeight /(delta);
		double top = Zero - (pRecords->m_records.at(i).max-min) * nHeight /(delta);
		double bottom = Zero - (pRecords->m_records.at(i).min-min) * nHeight /(delta);
		//st.Format ("pRecords->m_records.at(i).close-min=%4.4f,pRecords->m_records.at(i).open-min=%4.4f,pRecords->m_records.at(i).max-min=%4.4f,pRecords->m_records.at(i).min-min=%4.4f",pRecords->m_records.at(i).close-min,pRecords->m_records.at(i).open-min,pRecords->m_records.at(i).max-min,pRecords->m_records.at(i).min-min);
		//AfxMessageBox(st);
		st.Format("close=%4.4f,open =%4.4f,top=%4.4f,bottom=%4.4f",close,open,top,bottom);
		//AfxMessageBox(st);
		if(lab++%6 == 0)
		{	
			if(pRecords->TableName=="五分钟" || pRecords->TableName == "三十分钟") fmt = "%d %H:%M";
			if(pRecords->TableName=="小时") fmt = "%d日%H点";
			if(pRecords->TableName=="日" || pRecords->TableName=="周") fmt = "%m月%d日";
			if(pRecords->TableName=="月") fmt = "%y年%m月";
			pDC->TextOut(nWidth-25,Zero+5,pRecords->m_records.at(i).DateTime.Format(fmt));
			
			pDC->SelectObject(&pFace->m_GrayPen);
			pDC->MoveTo(nWidth,Zero);
			pDC->LineTo(nWidth,30);
		}
		
		//close与open的比较与坐标系有关,大的值其坐标值反而小
		if(close<open) 
		{
			pDC->SelectObject(&pFace->m_RedBarPen);
			pDC->SelectObject(&pFace->m_RedBarBrush);
		}else
		if(close>open) 
		{
			pDC->SelectObject(&pFace->m_GreenBarPen);
			pDC->SelectObject(&pFace->m_GreenBarBrush);
		}else
		{
			pDC->SelectObject(&pFace->m_YellowBarPen);
			pDC->SelectObject(&pFace->m_YellowBarBrush);
			pDC->MoveTo(nWidth-2,open);
			pDC->LineTo(nWidth+3,close);
		}
		
		pDC->Rectangle(nWidth-2,open,nWidth+3,close);
		pDC->MoveTo(nWidth,top);
		pDC->LineTo(nWidth,bottom);
		nWidth -= 10;
	}

	//画移动平均线1
	nWidth = pFace->m_rect.Width() - 60;
	if(P1>0)
	{
		pDC->SelectObject(&pFace->m_RedPen);
		double avg1=0,avg2=0;
		for(int i = pRecords->m_records.size()-1;i>pRecords->m_records.size()-1-P1;i--)
		{
			int n = i<0? 0:i;
			avg1 += pRecords->m_records.at(n).close;
		}
		avg1 /= P1;
		nWidth -= 10;
		for(i = pRecords->m_records.size()-2;i>=0;i--)
		{
			if(nWidth<3) break;
			for(int j = 0;j<P1;j++)
			{
				int n = i-1-j<0? 0:i-1-j;
				avg2 += pRecords->m_records.at(n).close;
			}
			avg2 /= P1;
			int y1 = Zero - (avg1-min) * nHeight / delta;
			int y2 = Zero - (avg2-min) * nHeight / delta;
			int x1 = nWidth+10;
			int x2 = nWidth;
			if(y1<30 && y2<30 || y1>Zero && y2>Zero)
			{
				avg1 = avg2;
				avg2 = 0;
				nWidth -= 10;
				continue;
			}
			if(y2<30) 
			{
				x2 = (y1-30) * 10 / (y2 - y1) + nWidth + 10;
				y2 = 30;
			}
			if(y1<30) 
			{
				x1 = (30-y2) * 10 / (y1 - y2) + nWidth;
				y1 = 30;
			}

			if(y2>Zero) 
			{
				x2 = (y1-Zero) * 10 / (y2 - y1) + nWidth + 10;
				y2 = Zero;
			}
			if(y1>Zero) 
			{
				x1 = (Zero-y2) * 10 / (y1 - y2) + nWidth;
				y1 = Zero;
			}
			pDC->MoveTo(x1,y1);
			pDC->LineTo(x2,y2);
			avg1 = avg2;
			avg2 = 0;
			nWidth -= 10;
		}
	}		

	//画移动平均线2
	nWidth = pFace->m_rect.Width() - 60;
	if(P2>0)
	{
		pDC->SelectObject(&pFace->m_GreenPen);
		double avg1=0,avg2=0;
		for(int i = pRecords->m_records.size()-1;i>pRecords->m_records.size()-1-P2;i--)
		{
			int n = i<0? 0:i;
			avg1 += pRecords->m_records.at(n).close;
		}
		avg1 /= P2;
		nWidth -= 10;
		for(i = pRecords->m_records.size()-2;i>=0;i--)
		{
			if(nWidth<3) break;
			for(int j = 0;j<P2;j++)
			{
				int n = i-1-j<0? 0:i-1-j;
				double s = pRecords->m_records.at(n).close;
				CString t = pRecords->m_records.at(n).DateTime.Format("%y-%m-%d %H:%M:%S");
				avg2 += pRecords->m_records.at(n).close;
			}
			avg2 /= P2;
			int y1 = Zero - (avg1-min) * nHeight / delta;
			int y2 = Zero - (avg2-min) * nHeight / delta;
			int x1 = nWidth+10;
			int x2 = nWidth;
			if(y1<30 && y2<30 || y1>Zero && y2>Zero)
			{
				avg1 = avg2;
				avg2 = 0;
				nWidth -= 10;
				continue;
			}
			if(y2<30) 
			{
				x2 = (y1-30) * 10 / (y2 - y1) + nWidth + 10;
				y2 = 30;
			}
			if(y1<30) 
			{
				x1 = (30-y2) * 10 / (y1 - y2) + nWidth;
				y1 = 30;
			}

			if(y2>Zero) 
			{
				x2 = (y1-Zero) * 10 / (y2 - y1) + nWidth + 10;
				y2 = Zero;
			}
			if(y1>Zero) 
			{
				x1 = (Zero-y2) * 10 / (y1 - y2) + nWidth;
				y1 = Zero;
			}
			pDC->MoveTo(x1,y1);
			pDC->LineTo(x2,y2);
			avg1 = avg2;
			avg2 = 0;
			nWidth -= 10;
		}
	}

	//画移动平均线3
	nWidth = pFace->m_rect.Width() - 60;
	if(P3>0)
	{
		pDC->SelectObject(&pFace->m_YellowPen);
		double avg1=0,avg2=0;
		for(int i = pRecords->m_records.size()-1;i>pRecords->m_records.size()-1-P3;i--)
		{
			int n = i<0? 0:i;
			avg1 += pRecords->m_records.at(n).close;
		}
		avg1 /= P3;
		nWidth -= 10;
		for(i = pRecords->m_records.size()-2;i>=0;i--)
		{
			if(nWidth<3) break;
			for(int j = 0;j<P3;j++)
			{
				int n = i-1-j<0? 0:i-1-j;
				avg2 += pRecords->m_records.at(n).close;
			}
			avg2 /= P3;
			int y1 = Zero - (avg1-min) * nHeight / delta;
			int y2 = Zero - (avg2-min) * nHeight / delta;
			int x1 = nWidth+10;
			int x2 = nWidth;
			if(y1<30 && y2<30 || y1>Zero && y2>Zero)
			{
				avg1 = avg2;
				avg2 = 0;
				nWidth -= 10;
				continue;
			}
			if(y2<30) 
			{
				x2 = (y1-30) * 10 / (y2 - y1) + nWidth + 10;
				y2 = 30;
			}
			if(y1<30) 
			{
				x1 = (30-y2) * 10 / (y1 - y2) + nWidth;
				y1 = 30;
			}

			if(y2>Zero) 
			{
				x2 = (y1-Zero) * 10 / (y2 - y1) + nWidth + 10;
				y2 = Zero;
			}
			if(y1>Zero) 
			{
				x1 = (Zero-y2) * 10 / (y1 - y2) + nWidth;
				y1 = Zero;
			}
			pDC->MoveTo(x1,y1);
			pDC->LineTo(x2,y2);
			avg1 = avg2;
			avg2 = 0;
			nWidth -= 10;
		}
	}

	pFace->m_lpLayer[1]->ReleaseDC(layer);
	pFace->m_lpLayer[0]->BltFast(0,0,pFace->m_lpLayer[1],CRect(0,0,pFace->m_rect.Width(),pFace->m_rect.Height()),DDBLTFAST_WAIT);
	pFace->m_lpPSur->BltFast(pFace->m_rect.left,pFace->m_rect.top,pFace->m_lpLayer[0],CRect(0,0,pFace->m_rect.Width(),pFace->m_rect.Height()),DDBLTFAST_WAIT);
}




⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -