天天看點

VC++ 源碼實作通達信公式管理器

效果圖

VC++ 源碼實作通達信公式管理器

前段時間,因業務需要,寫了這樣一個軟體,同樣的頁面已經是第2次寫了,第1次大約5年前的事情了,因為代碼遺失,于是重新寫。頁面看似複雜,實作起來非常簡單。

第一步:參照通達信的公式管理器核心檔案TCalc.dll,導出資源檔案(TCalc.rc),這樣界面基本上顯現出來了,接下來就是把這些頁面進行整合(頁面調用)。

VC++ 源碼實作通達信公式管理器

第二步:提取公式清單資訊

enum formula_type : unsigned char {
	ftFrom,
	ftTechnical_Indicator_Formula,// 技術名額公式
	ftConditional_Sel_Stock_Formula,	// 自選股名額公式
	ftExpert_System_Formula,	// 系統專家公式
	ftColorful_Kline_Formula,	// 五彩K線公式
	ftTo,
};

typedef struct _Formula_Parameter
{
	char _name[16];//參數
	union
	{
		char _value[4][16];
		struct  
		{
			char _min[16];//最小
			char _max[16];//最大
			char _default[16];//預設
			char _step[16];//步長
		};
	};
}Formula_Parameter;

// 技術名額公式
typedef struct _Technical_Indicator_Formula
{
	bool is_system;//是否系統公式 1-是 0-否
	bool is_common;//是否系統公式 1-是 0-否

	char name[32];// 公式名稱

	bool is_protected;//密碼保護

	char password[16];//密碼

	bool type_disable;
	char _type;//公式類型 
	/*
	技術名額公式
		0 - 大勢型
		1 - 超買超賣型
		2 - 趨勢性
		3 - 能量型
		4 - 成交量型
		5 - 均線型
		6 - 圖表型
		7 - 路徑型
		8 - 停損型
		9 - 交易型
		10 - 神系
		11 - 龍系
		12 - 鬼系
		13 - 其他系
		14 - 特色型
		15 - 其他類型
	條件選股公式
		0 - 名額條件
		1 - 基本面
		2 - 即時盤中
		3 - 走勢特征
		4 - 形态特征
		5 - 其他類型
	專家系統公式
		0 -
	五彩K線公式
	*/

	bool draw_disable;
	char draw_line_method;//畫線方法
	/*
	0 - 副圖
	1 - 主圖疊加
	2 - 副圖(疊加K線)
	3 - 副圖(疊加美國線)
	4 - 副圖(疊加收盤站線)
	5 - 主圖替換
	*/

	char desp[64];//公式描述

	char version[16];//公式版本

	char show_decimal;//顯示小數
	/*
	0 - 預設位數
	1 - 品種小數位數
	2 - 品種小數位數 + 1
	3 - 固定0位
	4 - 固定1位
	5 - 固定2位
	6 - 固定3位
	7 - 固定4位
	*/

	Formula_Parameter parameters[16];//參數

	char formula_text[4096];//公式文本内容

	char trade_rules;//交易法則
	/*
	0 - 無
	1 - 左手
	2 - 右手
	*/

	bool coordinate_disable;
	char coordinate_position[64];//坐标線位置,最多6個,用分号分隔

	bool extract_disable;
	char extract_y_axis[4][16];//額外Y軸分界
}Technical_Indicator_Formula;

//條件選股公式
typedef struct _Conditional_Sel_Stock_Formula
{
	bool is_system;//是否系統公式 1-是 0-否
	bool is_common;//是否系統公式 1-是 0-否

	char name[32];// 公式名稱

	bool is_protected;//密碼保護

	char password[16];//密碼

	char _type;//公式類型 
	/*
	條件選股公式
		0 - 名額條件
		1 - 基本面
		2 - 即時盤中
		3 - 走勢特征
		4 - 形态特征
		5 - 其他類型
	*/

	char right_to_use;//使用複權
	/*
	0 - 預設設定
	1 - 恒不複權
	*/

	char desp[64];//公式描述

	char version[16];//公式版本

	Formula_Parameter parameters[16];//參數

	char formula_text[4096];//公式文本内容
}Conditional_Sel_Stock_Formula;

//專家系統公式
typedef struct _Expert_System_Formula
{
	bool is_system;//是否系統公式 1-是 0-否
	bool is_common;//是否系統公式 1-是 0-否

	char name[32];// 公式名稱

	bool is_protected;//密碼保護

	char password[16];//密碼

	char desp[64];//公式描述

	char version[16];//公式版本

	Formula_Parameter parameters[16];//參數

	char formula_text[4096];//公式文本内容
}Expert_System_Formula;

//五彩K線公式
typedef struct _Colorful_Kline_Formula
{
	bool is_system;//是否系統公式 1-是 0-否
	bool is_common;//是否系統公式 1-是 0-否

	char name[32];// 公式名稱

	bool is_protected;//密碼保護

	char password[16];//密碼

	char desp[64];//公式描述

	char version[16];//公式版本

	Formula_Parameter parameters[16];//參數

	char formula_text[4096];//公式文本内容
}Colorful_Kline_Formula;
           
class formula
{
public:
	formula();
	~formula();

	std::vector<Formula_Struct*> m_queFormulas;

private:
	void init();
};

void formula::init()
{
	// 技術名額公式
	Formula_Struct formula_Struct;

	//0 - 大勢型
	memset(&formula_Struct, 0, sizeof(formula_Struct));
	formula_Struct.is_root = true;
	strcpy_s(formula_Struct.name, "大勢型");// 公式名稱
	formula_Struct.subtype = 1;
	formula_Struct.formulatype = formula_type::ftTechnical_Indicator_Formula;
	m_queFormulas.push_back(formula_Struct.clone());

	memset(&formula_Struct, 0, sizeof(formula_Struct));
	formula_Struct.subtype = 0;
	formula_Struct.is_system = true;
	strcpy_s(formula_Struct.name, "ABI");// 公式名稱
	formula_Struct.is_protected = false;//密碼保護
	formula_Struct.draw_line_method  = 0;//畫線方法
	strcpy_s(formula_Struct.desp, "絕對廣量名額");//公式描述
	strcpy_s(formula_Struct.version, "0");//公式版本
	formula_Struct.show_decimal = 0;//顯示小數
	strcpy_s(formula_Struct.formula_text, "ABI:100*ABS(ADVANCE-DECLINE)/(ADVANCE+DECLINE);\n");//公式文本内容
	strcat_s(formula_Struct.formula_text, "MAABI:EMA(ABI,M);");
	strcpy_s(formula_Struct.parameters[0]._name, "M");//參數
	strcpy_s(formula_Struct.parameters[0]._min, _T("2.00"));
	strcpy_s(formula_Struct.parameters[0]._max, _T("100.00"));
	strcpy_s(formula_Struct.parameters[0]._default, _T("10.00"));	
	formula_Struct.trade_rules = 1;//交易法則
	strcpy_s(formula_Struct.coordinate_position, "自動");//坐标線位置,最多6個,用分号分隔
	formula_Struct.formulatype = formula_type::ftTechnical_Indicator_Formula;
	m_queFormulas.push_back(formula_Struct.clone());

	memset(&formula_Struct, 0, sizeof(formula_Struct));
	formula_Struct.subtype = 0;
	formula_Struct.is_system = true;
	strcpy_s(formula_Struct.name, "ADL");// 公式名稱
	formula_Struct.is_protected = false;//密碼保護
	formula_Struct.draw_line_method = 0;//畫線方法
	strcpy_s(formula_Struct.desp, "騰落名額");//公式描述
	strcpy_s(formula_Struct.version, "0");//公式版本
	formula_Struct.show_decimal = 0;//顯示小數
	strcpy_s(formula_Struct.formula_text, "ADL:SUM(ADVANCE-DECLINE,0);\n");//公式文本内容
	strcat_s(formula_Struct.formula_text, "MAADL:MA(ADL,M);");
	strcpy_s(formula_Struct.parameters[0]._name, "M");//參數
	strcpy_s(formula_Struct.parameters[0]._min, _T("2.00f"));
	strcpy_s(formula_Struct.parameters[0]._max, _T("60.00f"));
	strcpy_s(formula_Struct.parameters[0]._default, _T("7.00f"));	
	formula_Struct.trade_rules = 1;//交易法則
	strcpy_s(formula_Struct.coordinate_position, "自動");//坐标線位置,最多6個,用分号分隔
	formula_Struct.formulatype = formula_type::ftTechnical_Indicator_Formula;
	m_queFormulas.push_back(formula_Struct.clone());

	memset(&formula_Struct, 0, sizeof(formula_Struct));
	formula_Struct.subtype = 0;
	formula_Struct.is_system = true;
	strcpy_s(formula_Struct.name, "ADR");// 公式名稱
	formula_Struct.is_protected = false;//密碼保護
	formula_Struct.draw_line_method = 0;//畫線方法
	strcpy_s(formula_Struct.desp, "漲跌比率");//公式描述
	strcpy_s(formula_Struct.version, "0");//公式版本
	formula_Struct.show_decimal = 0;//顯示小數
	strcpy_s(formula_Struct.formula_text, "ADR:SUM(ADVANCE,N)/SUM(DECLINE,N);\n");//公式文本内容
	strcat_s(formula_Struct.formula_text, "MAADR:MA(ADR,M);");
	strcpy_s(formula_Struct.parameters[0]._name, "N");//參數
	strcpy_s(formula_Struct.parameters[0]._min, _T("2.00f"));
	strcpy_s(formula_Struct.parameters[0]._max, _T("100.00f"));
	strcpy_s(formula_Struct.parameters[0]._default, _T("10.00f"));
	strcpy_s(formula_Struct.parameters[1]._name, "M");//參數
	strcpy_s(formula_Struct.parameters[1]._min, _T("2.00f"));
	strcpy_s(formula_Struct.parameters[1]._max, _T("60.00"));
	strcpy_s(formula_Struct.parameters[1]._default, _T("6.00"));
	formula_Struct.trade_rules = 1;//交易法則
	strcpy_s(formula_Struct.coordinate_position, "自動");//坐标線位置,最多6個,用分号分隔
	strcpy_s(formula_Struct.extract_y_axis[0], "0.50");
	strcpy_s(formula_Struct.extract_y_axis[1], "1.00");
	strcpy_s(formula_Struct.extract_y_axis[2], "1.50");
	formula_Struct.formulatype = formula_type::ftTechnical_Indicator_Formula;
	m_queFormulas.push_back(formula_Struct.clone());

    ......
}
           

 第三步:将提取的公式結構填充顯示到清單樹

void CTCalcDlg::InitFormulaGroupTree()
{
	CTreeCtrl* pTree = reinterpret_cast<CTreeCtrl*>(GetDlgItem(IDC_TREE_2001));
	pTree->LockWindowUpdate();
	pTree->DeleteAllItems();

	HTREEITEM hRoot = pTree->InsertItem(_T("技術名額公式"), 32, 32);
	pTree->SetItemData(hRoot, ftTechnical_Indicator_Formula * 1000);

	std::vector<Formula_Struct*>::iterator iter = globalFormula.m_queFormulas.begin();
	for (; iter != globalFormula.m_queFormulas.end(); iter++)
	{
		Formula_Struct* pFormula = *iter;
		if (pFormula->is_root && pFormula->formulatype == ftTechnical_Indicator_Formula)
		{
label_100:
			HTREEITEM hChild = pTree->InsertItem(pFormula->name, 3, 3, hRoot);
			pTree->SetItemData(hChild, (DWORD)pFormula);

			for (++iter; iter != globalFormula.m_queFormulas.end(); iter++)
			{
				pFormula = *iter;

				if (pFormula->formulatype != ftTechnical_Indicator_Formula)
					break;

				if (pFormula->is_root)
					goto label_100;

				CString sItemText;
				if (pFormula->is_system)
					sItemText.Format(_T("%s %s(系統)"), pFormula->name, pFormula->desp);
				else
					sItemText.Format(_T("%s %s(使用者)"), pFormula->name, pFormula->desp);
				HTREEITEM hSubChild = NULL;
				if (pFormula->is_common)
					hSubChild = pTree->InsertItem(sItemText, 30, 30, hChild);
				else if (pFormula->is_protected)
					hSubChild = pTree->InsertItem(sItemText, 17, 17, hChild);
				else
					hSubChild = pTree->InsertItem(sItemText, 15, 15, hChild);
				pTree->SetItemData(hSubChild, (DWORD)pFormula);
			}


			break;
		}
	}

	pTree->Expand(hRoot, TVM_EXPAND);
	
	hRoot = pTree->InsertItem(_T("條件選股公式"), 32, 32);
	pTree->SetItemData(hRoot, ftConditional_Sel_Stock_Formula * 1000);

	iter = globalFormula.m_queFormulas.begin();
	for (; iter != globalFormula.m_queFormulas.end(); iter++)
	{
		Formula_Struct* pFormula = *iter;
		if (pFormula->is_root && pFormula->formulatype == ftConditional_Sel_Stock_Formula)
		{
label_101:
			HTREEITEM hChild = pTree->InsertItem(pFormula->name, 3, 3, hRoot);
			pTree->SetItemData(hChild, (DWORD)pFormula);

			for (++iter; iter != globalFormula.m_queFormulas.end(); iter++)
			{
				pFormula = *iter;
				if (pFormula->formulatype != ftConditional_Sel_Stock_Formula)
					break;
				
				if (pFormula->is_root)
					goto label_101;

				CString sItemText;
				if (pFormula->is_system)
					sItemText.Format(_T("%s %s(系統)"), pFormula->name, pFormula->desp);
				else
					sItemText.Format(_T("%s %s(使用者)"), pFormula->name, pFormula->desp);
				HTREEITEM hSubChild = NULL;
				if (pFormula->is_common)
					hSubChild = pTree->InsertItem(sItemText, 30, 30, hChild);
				else if (pFormula->is_protected)
					hSubChild = pTree->InsertItem(sItemText, 17, 17, hChild);
				else
					hSubChild = pTree->InsertItem(sItemText, 15, 15, hChild);
				pTree->SetItemData(hSubChild, (DWORD)pFormula);
			}
			break;
		}
	}

	hRoot = pTree->InsertItem(_T("專家系統公式"), 32, 32);
	pTree->SetItemData(hRoot, ftExpert_System_Formula * 1000);

	iter = globalFormula.m_queFormulas.begin();
	for (; iter != globalFormula.m_queFormulas.end(); iter++)
	{
		Formula_Struct* pFormula = *iter;
		if (pFormula->formulatype == ftExpert_System_Formula)
		{
			for (; iter != globalFormula.m_queFormulas.end(); iter++)
			{
				Formula_Struct* pFormula = *iter;
				if (pFormula->formulatype != ftExpert_System_Formula)
					break;

				CString sItemText;
				if (pFormula->is_system)
					sItemText.Format(_T("%s %s(系統)"), pFormula->name, pFormula->desp);
				else
					sItemText.Format(_T("%s %s(使用者)"), pFormula->name, pFormula->desp);
				HTREEITEM hChild = NULL;
				if (pFormula->is_common)
					hChild = pTree->InsertItem(sItemText, 30, 30, hRoot);
				else if (pFormula->is_protected)
					hChild = pTree->InsertItem(sItemText, 17, 17, hRoot);
				else
					hChild = pTree->InsertItem(sItemText, 15, 15, hRoot);
				pTree->SetItemData(hChild, (DWORD)pFormula);
			}
			break;
		}
	}

	hRoot = pTree->InsertItem(_T("五彩K線公式"), 32, 32);
	pTree->SetItemData(hRoot, ftColorful_Kline_Formula * 1000);

	iter = globalFormula.m_queFormulas.begin();
	for (; iter != globalFormula.m_queFormulas.end(); iter++)
	{
		Formula_Struct* pFormula = *iter;
		if (pFormula->formulatype == ftColorful_Kline_Formula)
		{
			for (; iter != globalFormula.m_queFormulas.end(); iter++)
			{
				Formula_Struct* pFormula = *iter;
				if (pFormula->formulatype != ftColorful_Kline_Formula)
					break;

				CString sItemText;
				if (pFormula->is_system)
					sItemText.Format(_T("%s %s(系統)"), pFormula->name, pFormula->desp);
				else
					sItemText.Format(_T("%s %s(使用者)"), pFormula->name, pFormula->desp);
				HTREEITEM hChild = NULL;
				if (pFormula->is_common)
					hChild = pTree->InsertItem(sItemText, 30, 30, hRoot);
				else if (pFormula->is_protected)
					hChild = pTree->InsertItem(sItemText, 17, 17, hRoot);
				else
					hChild = pTree->InsertItem(sItemText, 15, 15, hRoot);
				pTree->SetItemData(hChild, (DWORD)pFormula);
			}
			break;
		}
	}

	pTree->UnlockWindowUpdate();
}
           

至此,清單數結構就顯示出來了。