天天看点

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

至此,列表数结构就显示出来了。