300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 股票模拟交易软件(一)待续

股票模拟交易软件(一)待续

时间:2022-10-16 00:59:02

相关推荐

股票模拟交易软件(一)待续

最近比较忙,一直没时间写博客。今天我们就开讲股票模拟交易软件。

股票模拟交易软件主要包括以下几个部分:

1.股票行情服务

2.交易终端

3.柜台系统

4.中间件(我们的叫法,其实就是一个中间处理流程)

5.报盘系统

6.撮合系统

7.成交回报系统

8.清算系统

一、行情服务我们采用socket长连接的方式从行情服务器上获取数据

首先我们登录行情服务器:

if (userLogin.ChenckUserLoginConnection(serverAddress, serverPort, ref socket))

{

if (userLogin.SendLoginMessage(serverUsername, serverPassword, socket))

{

marketFlags = new MarketModel.TDFDefine_Data_MarketFlag[MarketModel.MarketFlagArrayLength];

loginAnswer = new MarketModel.TDFDefine_LoginAnswer();

if (userLogin.ReceiveLoginAnswer(ref loginAnswer, ref marketFlags, socket))

{

IOHelper.WriteLog("接收登陆信息成功");

//获取证劵代码列表

LstockModel = OfferStockCodeList(-1, ref errorMessage);

StockIndex stockIndex = new StockIndex();

//获取本日编号与股票代码索引表,建立行情空表

stockIndex.CreateStockIndexList(LstockModel, ref stockIndexLists_Code, ref immediateMarketModels, ref errorMessage);

//获取行情代码

OfferImmediateMarketModel(nReceiveDataFlags, 1012, ref errorMessage);

loginState = true;

errorMessage = 0;

}

else

{

IOHelper.WriteLog("接收登陆信息失败");

loginState = false;

errorMessage = 3;

}

}

else

{

IOHelper.WriteLog("发送登录请求失败");

loginState = false;

errorMessage = 2;

}

}

else

{

errorMessage = 1;

loginState = false;

IOHelper.WriteLog("连接行情服务器失败,请查看日志文件!");

}

}

然后填充我们需要的内存表

//获取证劵代码列表

LstockModel = OfferStockCodeList(-1, ref errorMessage);

StockIndex stockIndex = new StockIndex();

//获取本日编号与股票代码索引表,建立行情空表

stockIndex.CreateStockIndexList(LstockModel, ref stockIndexLists_Code, ref immediateMarketModels, ref errorMessage);

接下来我们获取行情:

OfferImmediateMarketModel(nReceiveDataFlags, 1012, ref errorMessage);

再看我们发送的行情数据请求

public int SendRequestMarketData(string MarketFlag, Socket socket, int nReceiveDataFlags)

{

MarketModel.TDFDefine_UnionMsgHeadMarketData unionMsgHeadMarketData = new MarketModel.TDFDefine_UnionMsgHeadMarketData();

unionMsgHeadMarketData.tmsg.sFlags = Convert.ToUInt16(MarketModel.TDFTELEFLAGS);

unionMsgHeadMarketData.tmsg.sDataType = Convert.ToUInt16(MarketModel.ID_TDFTELE_REQDATA);

unionMsgHeadMarketData.tmsg.nTime = 0;

unionMsgHeadMarketData.tmsg.nOrder = 0;

unionMsgHeadMarketData.trmd.chMarketFlag = MarketFlag;

unionMsgHeadMarketData.trmd.nFlags = nReceiveDataFlags == 1 ? MarketModel.ID_HDFDATAFLAGS_RETRANSALTE : 0x00;

unionMsgHeadMarketData.trmd.nFlags |= MarketModel.ID_HDFDATAFLAGS_NOTRANSACTION;

unionMsgHeadMarketData.trmd.nFlags |= MarketModel.ID_HDFDATAFLAGS_NOABQUEUE;

unionMsgHeadMarketData.trmd.nFlags |= MarketModel.ID_HDFDATAFLAGS_NOINDEX;

//unionMsgHeadMarketData.trmd.nFlags |= MarketModel.ID_HDFDATAFLAGS_NOMARKETOVERVIEW;

unionMsgHeadMarketData.trmd.nFlags |= MarketModel.ID_TDFTELE_CLOSE;

//unionMsgHeadMarketData.trmd.nFlags |= DataDefine.ID_HDFDATAFLAGS_COMPRESSED; //启用数据压缩

byte[] nbyte = StructTransform.StructToBytes(unionMsgHeadMarketData);

int i = socket.Send(nbyte, nbyte.Length, 0);

return i;

}

有的朋友可能不知道为什么会有|=了,其实unionMsgHeadMarketData.trmd.nFlags |= MarketModel.ID_HDFDATAFLAGS_NOTRANSACTION;等价于

unionMsgHeadMarketData.trmd.nFlags = unionMsgHeadMarketData.trmd.nFlags | MarketModel.ID_HDFDATAFLAGS_NOTRANSACTION;

与运算符:同位上面00得0,01得1,11得1,采用与运算符来做能够节省控制变量。不同与运算符的请自己Google上查一下。

在获取行情服务器时还有一个特点就是我们采用了大量的结构体。为什么采用结构体呢?因为结构体的长度是确定的,这样我们在发送和接收行情数据就方便很多了。

我们来看看怎么取结构体的长度:

Marshal.SizeOf(typeof(MarketModel.TDFDefine_MsgHead))

获取结构体:MarketModel.TDFDefine_MsgHead 的长度

Marshal 记得要引入命名空间 System.Runtime.InteropServices;

我们再来看看下面几个方法:

方法一:

public static byte[] StructToBytes(object structObj)

{

//得到结构体的大小

int size = Marshal.SizeOf(structObj);

//创建byte数组

byte[] bytes = new byte[size];

//分配结构体大小的内存空间

IntPtr structPtr = Marshal.AllocHGlobal(size);

//将结构体拷到分配好的内存空间

Marshal.StructureToPtr(structObj, structPtr, false);

//从内存空间拷到byte数组

Marshal.Copy(structPtr, bytes, 0, size);

//释放内存空间

Marshal.FreeHGlobal(structPtr);

//返回byte数组

return bytes;

}

方法二:

/// <summary>

/// byte数组转结构体

/// </summary>

/// <param name="bytes">byte数组</param>

/// <param name="type">结构体类型</param>

/// <returns>转换后的结构体</returns>

public static object BytesToStuct(byte[] bytes, Type type)

{

//得到结构体的大小

int size = Marshal.SizeOf(type);

//byte数组长度小于结构体的大小

if (size > bytes.Length)

{

//返回空

return null;

}

//分配结构体大小的内存空间

IntPtr structPtr = Marshal.AllocHGlobal(size);

//将byte数组拷到分配好的内存空间

Marshal.Copy(bytes, 0, structPtr, size);

//将内存空间转换为目标结构体

object obj = Marshal.PtrToStructure(structPtr, type);

//释放内存空间

Marshal.FreeHGlobal(structPtr);

//返回结构体

return obj;

}

方法三:

public static byte[] BytesCopy(byte[] bytSource, byte[] bytTag, int startIndex, int size)

{

try

{

IntPtr bytePtr = Marshal.AllocHGlobal(size);

Marshal.Copy(bytSource, 0, bytePtr, size);

Marshal.Copy(bytePtr, bytTag, startIndex, size);

Marshal.FreeHGlobal(bytePtr);

return bytTag;

}

catch { return null; }

}

方法四:

public static object BytesToStruct(byte[] structObj, int startIndex, int size, Type type)

{

IntPtr structPtr = Marshal.AllocHGlobal(size);

Marshal.Copy(structObj, startIndex, structPtr, size);

object obj = Marshal.PtrToStructure(structPtr, type);

Marshal.FreeHGlobal(structPtr);

return obj;

}

方法一:将结构体转化成为二进制数组

方法二:把二进制数组还原成为结构体

方法三:不用循环的方式拷贝数组中的部分

方法四:把二进制数组中的部分还原成为结构体

以上四个方法是常用的结构体和二进制数组中间的转化方法,有兴趣的朋友可以好好的了解一下。

本次先讲到这里吧。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。