As you know, the CTP interface of futures is provided by the technology company of the previous period. The source code and examples it provides are written in C + + language, which is not convenient to use. For example, I need a database, a program, a K-line chart, and functions like this. I need to do a lot of things before I place an order Writing in C + + can be cumbersome. But C ා is not afraid to do these troublesome things. C ා is used to do dirty work. You give C ා the interface and application logic. C + + only needs to manage one thing of its own - how to talk with the exchange. In this way, the workload will be much smaller.
In fact, for most people, without a high-level language like C Chen, they can't do any work at all. For example, if I want to place an order, how can I place an order in C + +, in the black window, enter the contract code, price, number of hands You can't finish a list until you hit the keyboard, right? But in the C interface, you only need to click a button:
It's the "hang buy" button. I click it. In a flash, the purchase is finished. In this moment, the program did a series of things for me:
● see which contract I want to buy;
● read the latest interface of the contract, read the preset offset value of the hanging order, and calculate the price of the hanging order;
● read the default number of hands;
● prepare the declaration, update the serial number of the declaration and record the information of the declaration;
● pre check this order (whether there is self closing risk, whether the application serial number is compliant, whether the funds are sufficient, whether it is compliant in transaction time and other aspects);
● whether there is an old order to be withdrawn (sometimes it is necessary to withdraw the old order and then issue a new one, such as when closing positions);
● whether there is reverse order in the account to be hedged, and if so, whether to open or close the position;
● issue order to transaction module;
● issue order to C + + module;
● report to exchange.
In this series of things, all C + + has to do is to report to the exchange, that is, ReqOrderInsert.
All the long winded matters in front are arranged by C Chen.
If it's written in C + +, the workload can be imagined (in fact, it's not feasible for most programmers).
Although it seems that there are many things, the series just happened in about ten milliseconds.
This ten millisecond event, that is, it's written in C ා language, and it's also very long. Let's simplify it. First, we don't think about the report record, report verification and so on. Suppose that we click the button to directly report, so that we can see the relationship between C ා and C + +, then——
The code in C is:
///Location of dll output by C + + const string dllPath = @"CTP_se.dll"; ///Reference the single function in C + + (in C + +, the entry of the single is the function "﹣ ReqOrderInsert" [DllImport(dllPath, EntryPoint = "_ReqOrderInsert")] ///The single function of C ා, and the "extern" label determines that it should refer to the function "ReqOrderInsert" in C + + as specified in the previous sentence static extern void ReqOrderInsert( char[] BrokerID, //Brokerage company code (string, required) char[] InvestorID, //Investor code (string, required) char[] InstrumentID, //Contract code (string, required) char[] ExchangeID, //Exchange code (string, required) char[] OrderRef, //Entry reference (string, required) char[] UserID, //User code (string, no need to fill in "null") int OrderPriceType, //Entry price condition (required, 1 is any price, 2 is limit price, 3 is the best price, 4 is the latest price, //5 is the latest price floating up 1 tick, 6 is the latest price floating up 2 ticks, 7 is the latest price floating up 3 ticks, 8 is the selling price, //9 is one tick for selling one price floating upward, 10 is two ticks for selling one price floating upward, 11 is three ticks for selling one price floating upward, 12 is buying one price, //13 is one tick for the floating of buy one price, 14 is two ticks for the floating of buy one price, 15 is three ticks for the floating of buy one price, 16 is the fifth price) int Direction, //Buying and selling direction (1 for buying, - 1 for selling) int CombOffsetFlag, //Combined open flat sign (required, 1 is open, 0 is flat, - 1 is flat now, - 2 is flat yesterday, - 3 is strong flat, - 4 is strong minus, - 5 is local strong flat) int CombHedgeFlag, //Combination speculative hedging flag (required, 0 is speculation, 1 is arbitrage, 2 is hedging) double LimitPrice, //Price (real, required) int VolumeTotalOriginal, //Number of hands (required) int TimeCondition, //Validity type (required, 1 is to be completed immediately, otherwise it will be cancelled, 2 is to be valid in this section, 3 is to be valid on that day, generally fill in 3 //4 is valid before the specified date, 5 is valid before cancellation, 6 is valid for call auction) char[] GTDDate, //GTD date (string, no need to fill in "null") int VolumeCondition, //Volume type (required, 1 for any quantity, 2 for minimum quantity, 3 for all quantity, generally 1) int MinVolume, //Minimum volume (required) int ContingentCondition, //Trigger conditions (required, 1 is immediate, 2 is stop loss, 3 is win until win, 4 is embedded form, generally fill in 1 //5 is the latest price greater than the conditional price, 6 is the latest price greater than or equal to the conditional price, 7 is the latest price less than the conditional price, 8 is the latest price less than or equal to the conditional price, //9 is the selling price greater than the conditional price, 10 is the selling price greater than or equal to the conditional price, 11 is the selling price less than the conditional price, 12 is the selling price less than or equal to the conditional price, //13 is that the buy price is greater than the condition price, 14 is that the buy price is greater than or equal to the condition price, 15 is that the buy price is less than the condition price, 16 is that the buy price is less than or equal to the condition price) double StopPrice, //Stop loss price (real number, no need to fill in "0") int ForceCloseReason, //Strong flat reason (required, 0 is not strong flat, 1 is insufficient funds, 2 is customer over position, generally fill in 0 //3 is over position of members, 4 is non integral multiple of position, 5 is violation, 6 is other, 7 is close to delivery of natural person) int IsAutoSuspend, //Auto suspend flag (integer, required, generally 0, indicating no auto suspend) char[] BusinessUnit, //Business unit (string, no need to fill in "null") int RequestID, //Request number (integer, no need to fill in "Int32.MinValue") int UserForceClose, //User strong rating mark (integer, required, generally 0, no) int IsSwapOrder, //Swap list flag (integer, no need to fill in "Int32.MinValue") int tdClientI //Transaction communication thread No ); private void Hang on button_Click(object sender, EventArgs e) { string brokerID = "9999"; string userID = "071988"; string insID = "ni2003"; string exchangeID = "SHFE"; string ordID = "10000"; int direction = 1; int oc = 1; double price = 108590; int lot = 1; int tdClientI = 0; ReqOrderInsert(brokerID.ToCharArray(), userID.ToCharArray(), insID.ToCharArray(), exchangeID.ToCharArray(), ordID.ToCharArray(), null, 2, direction, oc, 0, price, lot, 3, null, 1, 1, 1, 0, 0, 0, null, Int32.MinValue, 0, Int32.MinValue, tdClientI); }
In C + +, the function that interfaces with the above C ා function is called "ReqOrderInsert":
///Declaration function in C + + int ReqOrderInsert(CThostFtdcInputOrderField* pInputOrder, int tdClientI) { string str_ref(pInputOrder->OrderRef); string insID(pInputOrder->InstrumentID); logWithTimeBUI(tdClientI, insID, "Trial report ordID." + str_ref); tdApiList::iterator i = tdAPIs.begin(); advance(i, tdClientI); int r = (*i)->ReqOrderInsert(pInputOrder, ++nRequestID); //Enter the network communication module officially provided in the previous issue and report to the exchange logBUI(tdClientI, insID, "Return" + toStr(r)); return r; } ///The ticket function of C + + and C ා docking CTP_API void __stdcall _ReqOrderInsert(char* BrokerID, char* InvestorID, char* InstrumentID, char* ExchangeID, char* OrderRef, char* UserID, int OrderPriceType, int Direction, int CombOffsetFlag, int CombHedgeFlag, double LimitPrice, int VolumeTotalOriginal, int TimeCondition, char* GTDDate, int VolumeCondition, int MinVolume, int ContingentCondition, double StopPrice, int ForceCloseReason, int IsAutoSuspend, char* BusinessUnit, int RequestID, int UserForceClose, int IsSwapOrder, int tdClientI) { CThostFtdcInputOrderField req; memset(&req, 0, sizeof(req)); if (BrokerID != NULL) strcpy(req.BrokerID, BrokerID);//Brokerage company code if (InvestorID != NULL) strcpy(req.InvestorID, InvestorID);//Investor code if (InstrumentID != NULL) strcpy(req.InstrumentID, InstrumentID);//Contract code if (ExchangeID != NULL) strcpy(req.ExchangeID, ExchangeID);//Affiliated exchange if (OrderRef != NULL) strcpy(req.OrderRef, OrderRef);//Invoice reference if (UserID != NULL) strcpy(req.UserID, UserID);//user designation codes if (OrderPriceType == 1) req.OrderPriceType = THOST_FTDC_OPT_AnyPrice;//Arbitrary price else if (OrderPriceType == 2) req.OrderPriceType = THOST_FTDC_OPT_LimitPrice;//Fixed price else if (OrderPriceType == 3) req.OrderPriceType = THOST_FTDC_OPT_BestPrice;//Best price else if (OrderPriceType == 4) req.OrderPriceType = THOST_FTDC_OPT_LastPrice;//Latest price else if (OrderPriceType == 5) req.OrderPriceType = THOST_FTDC_OPT_LastPricePlusOneTicks;//Latest price floating up 1 tick else if (OrderPriceType == 6) req.OrderPriceType = THOST_FTDC_OPT_LastPricePlusTwoTicks;//Latest price floating up 2 ticks else if (OrderPriceType == 7) req.OrderPriceType = THOST_FTDC_OPT_LastPricePlusThreeTicks;//Latest price floating up 3 ticks else if (OrderPriceType == 8) req.OrderPriceType = THOST_FTDC_OPT_AskPrice1;//Selling price else if (OrderPriceType == 9) req.OrderPriceType = THOST_FTDC_OPT_AskPrice1PlusOneTicks;//Sell one price floating up one tick else if (OrderPriceType == 10) req.OrderPriceType = THOST_FTDC_OPT_AskPrice1PlusTwoTicks;//Sell one price floating up 2 tickets else if (OrderPriceType == 11) req.OrderPriceType = THOST_FTDC_OPT_AskPrice1PlusThreeTicks;//Selling one price floating up three tickets else if (OrderPriceType == 12) req.OrderPriceType = THOST_FTDC_OPT_BidPrice1;//Buy one price else if (OrderPriceType == 13) req.OrderPriceType = THOST_FTDC_OPT_BidPrice1PlusOneTicks;//Buy one price float up one tick else if (OrderPriceType == 14) req.OrderPriceType = THOST_FTDC_OPT_BidPrice1PlusTwoTicks;//Buy one price floating up 2 tickets else if (OrderPriceType == 15) req.OrderPriceType = THOST_FTDC_OPT_BidPrice1PlusThreeTicks;//Buy one price floating up three tickets else if (OrderPriceType == 16) req.OrderPriceType = THOST_FTDC_OPT_FiveLevelPrice;//Five price else return;//Entry price conditions if (Direction > 0) req.Direction = THOST_FTDC_D_Buy;//buy else if (Direction < 0) req.Direction = THOST_FTDC_D_Sell;//sell else return;//Direction of business if (CombOffsetFlag == 1) req.CombOffsetFlag[0] = THOST_FTDC_OF_Open;//open else if (CombOffsetFlag == 0) req.CombOffsetFlag[0] = THOST_FTDC_OF_Close;//flat else if (CombOffsetFlag == -1) req.CombOffsetFlag[0] = THOST_FTDC_OF_CloseToday;//Ping Jin else if (CombOffsetFlag == -2) req.CombOffsetFlag[0] = THOST_FTDC_OF_CloseYesterday;//Ping yesterday else if (CombOffsetFlag == -3) req.CombOffsetFlag[0] = THOST_FTDC_OF_ForceClose;//Qiang Ping else if (CombOffsetFlag == -4) req.CombOffsetFlag[0] = THOST_FTDC_OF_ForceOff;//Strong reduction else if (CombOffsetFlag == -5) req.CombOffsetFlag[0] = THOST_FTDC_OF_LocalForceClose;//Local strengthening else return;//Combined Kaiping logo if (CombHedgeFlag == 0) req.CombHedgeFlag[0] = THOST_FTDC_HF_Speculation;//Speculation else if (CombHedgeFlag == 1) req.CombHedgeFlag[0] = THOST_FTDC_HF_Arbitrage;//Interest arbitrage else if (CombHedgeFlag == 2) req.CombHedgeFlag[0] = THOST_FTDC_HF_Hedge;//Hedging else return;//Portfolio speculative hedging mark if (LimitPrice > 0) req.LimitPrice = LimitPrice;//Price req.VolumeTotalOriginal = VolumeTotalOriginal;//Number if (TimeCondition == 1) req.TimeCondition = THOST_FTDC_TC_IOC;//Complete immediately, otherwise cancel else if (TimeCondition == 2) req.TimeCondition = THOST_FTDC_TC_GFS;//This section is valid. else if (TimeCondition == 3) req.TimeCondition = THOST_FTDC_TC_GFD;//good for the date of issue only else if (TimeCondition == 4) req.TimeCondition = THOST_FTDC_TC_GTD;//Valid before specified date else if (TimeCondition == 5) req.TimeCondition = THOST_FTDC_TC_GTC;//Effective before cancellation else if (TimeCondition == 6) req.TimeCondition = THOST_FTDC_TC_GFA;//Effective call auction else return;//Validity type if (GTDDate != NULL) strcpy(req.GTDDate, GTDDate);//GTD date if (VolumeCondition == 1) req.VolumeCondition = THOST_FTDC_VC_AV;//Any quantity else if (VolumeCondition == 2) req.VolumeCondition = THOST_FTDC_VC_MV;//Minimum quantity else if (VolumeCondition == 3) req.VolumeCondition = THOST_FTDC_VC_CV;//Total quantity else return;//Volume type req.MinVolume = MinVolume;//Minimum volume if (ContingentCondition == 1) req.ContingentCondition = THOST_FTDC_CC_Immediately;//immediately else if (ContingentCondition == 2) req.ContingentCondition = THOST_FTDC_CC_Touch;//Stop loss else if (ContingentCondition == 3) req.ContingentCondition = THOST_FTDC_CC_TouchProfit;//Stop win else if (ContingentCondition == 4) req.ContingentCondition = THOST_FTDC_CC_ParkedOrder;//Prepaid bill else if (ContingentCondition == 5) req.ContingentCondition = THOST_FTDC_CC_LastPriceGreaterThanStopPrice;//Latest price is greater than conditional price else if (ContingentCondition == 6) req.ContingentCondition = THOST_FTDC_CC_LastPriceGreaterEqualStopPrice;//Latest price is greater than or equal to conditional price else if (ContingentCondition == 7) req.ContingentCondition = THOST_FTDC_CC_LastPriceLesserThanStopPrice;//Latest price is less than conditional price else if (ContingentCondition == 8) req.ContingentCondition = THOST_FTDC_CC_LastPriceLesserEqualStopPrice;//Latest price is less than or equal to conditional price else if (ContingentCondition == 9) req.ContingentCondition = THOST_FTDC_CC_AskPriceGreaterThanStopPrice;//Selling price is higher than conditional price else if (ContingentCondition == 10) req.ContingentCondition = THOST_FTDC_CC_AskPriceGreaterEqualStopPrice;//Selling price is greater than or equal to the conditional price else if (ContingentCondition == 11) req.ContingentCondition = THOST_FTDC_CC_AskPriceLesserThanStopPrice;//Selling price less than conditional price else if (ContingentCondition == 12) req.ContingentCondition = THOST_FTDC_CC_AskPriceLesserEqualStopPrice;//Selling price less than or equal to conditional price else if (ContingentCondition == 13) req.ContingentCondition = THOST_FTDC_CC_BidPriceGreaterThanStopPrice;//Buy price is higher than condition price else if (ContingentCondition == 14) req.ContingentCondition = THOST_FTDC_CC_BidPriceGreaterEqualStopPrice;//Buy price is greater than or equal to the conditional price else if (ContingentCondition == 15) req.ContingentCondition = THOST_FTDC_CC_BidPriceLesserThanStopPrice;//Buy price less than conditional price else if (ContingentCondition == 16) req.ContingentCondition = THOST_FTDC_CC_BidPriceLesserEqualStopPrice;//Buy price less than or equal to conditional price else return;//Trigger condition if (StopPrice > 0) req.StopPrice = StopPrice;//Stop loss price if (ForceCloseReason == 0) req.ForceCloseReason = THOST_FTDC_FCC_NotForceClose;//Non strong flat else if (ForceCloseReason == 1) req.ForceCloseReason = THOST_FTDC_FCC_LackDeposit;//Insufficient funds else if (ForceCloseReason == 2) req.ForceCloseReason = THOST_FTDC_FCC_ClientOverPositionLimit;//Customer exceed warehouse else if (ForceCloseReason == 3) req.ForceCloseReason = THOST_FTDC_FCC_MemberOverPositionLimit;//Member super warehouse else if (ForceCloseReason == 4) req.ForceCloseReason = THOST_FTDC_FCC_NotMultiple;//Position is not an integral multiple else if (ForceCloseReason == 5) req.ForceCloseReason = THOST_FTDC_FCC_Violation;//Violation else if (ForceCloseReason == 6) req.ForceCloseReason = THOST_FTDC_FCC_Other;//Other else if (ForceCloseReason == 7) req.ForceCloseReason = THOST_FTDC_FCC_PersonDeliv;//Natural person close to delivery else return;//Cause of strong flat if (IsAutoSuspend > -2147483647) req.IsAutoSuspend = IsAutoSuspend;//Auto suspend flag if (BusinessUnit != NULL) strcpy(req.BusinessUnit, BusinessUnit);//Business unit if (RequestID > -2147483647) req.RequestID = RequestID;//Request number if (UserForceClose > -2147483647) req.UserForceClose = UserForceClose;//User strong evaluation mark if (IsSwapOrder > -2147483647) req.IsSwapOrder = IsSwapOrder;//Interchange single sign ReqOrderInsert(&req, tdClientI); }
There are a lot of codes involved in this. I'm sorry that I can't completely paste them here, because there are too many, too many. If you need to know more about it, you can chat with me in private. My QQ is 791269791 and wechat is minMove.
Here, I'll talk about the main ideas. Students who are familiar with C + + may understand it directly.
The problem we need to solve is to connect the C + + interface to C ා.
This is because:
1. We have to have C + +, because the interface officially provided in the last issue is C + +;
2. But C + + is troublesome. We don't want to write application logic with it;
3. It's easy to write with C ා, so we choose C ා;
4. But C ා needs to understand C + + "speaking", so it is necessary to connect the C + + interface to C ා.
What are the official interfaces in the last issue?
I'll show you the folders in my computer:
This is the final output directory of my futures software. The exe file is in it. Then there are many DLLs together with the exe file. Among them, the DLLs officially provided in the previous period are the three DLLs of "thostmduser api_se", "thostmtraderapi_se" and "WinDataCollect", which is the interface officially provided in the previous period.
"Thostmduserapi" is the market interface and "thostmtraderapi" is the transaction interface. These two DLLs have been used for ten years. I can write them down without looking at their strange names.
"WinDataCollect" is something that was only popularized in June last year. It's what the so-called "through certification" requires.
As an application, as an exe file, these DLLs are enough to talk to the exchange.
But as a developer, it's not enough. If you want to write the C + + part of the source code, what you need, which is officially from the last issue and is called "interface" in the legend, in addition to the three DLLs mentioned above, there are also some files, in general, these are:
error.dtd
error.xml
ThostFtdcMdApi.h
ThostFtdcTraderApi.h
ThostFtdcUserApiDataType.h
ThostFtdcUserApiStruct.h
thostmduserapi_se.dll
thostmduserapi_se.lib
thosttraderapi_se.dll
thosttraderapi_se.lib
DataCollect.h
WinDataCollect.dll
WinDataCollect.lib
The three dll files we just mentioned are in them. In addition, there are:
Library file: with the suffix of "lib", our C + + project can find the dll officially provided in the previous issue. A lib is paired with a dll. For example, "thosttradeapi_se. Lib" and "thosttradeapi_se. dll" are all transaction interfaces.
Header file: with "h" as the suffix, it can be opened with Notepad. You can clearly see its source code, because it is used for your reference. There are many official functions, which you can reference in C + + projects.
As for how to quote and place these documents, students who are familiar with C + + don't have to say they know them. Those who are not familiar with C + + don't understand them even if they say they don't understand them. They have to see the demonstration project to understand them. They can talk with me privately.
Instructions and returns
These are two important types of futures interface:
instructions
It's what I ask CTP to do for me or ask it.
For example, when I log in, I will tell it my user name, password, etc., which is the login instruction. For another example, I asked it for the service charge of contract ni2003, which belongs to the query instruction. All instructions are "what I said to CTP.".
Return
After I sent out the instruction, CTP replied to me, for example, if my login was successful, what is the handling fee of the contract I asked, which belongs to the return.
In addition, sometimes when I don't give instructions, CTP will also send messages to me, such as the market data of a contract and the transaction information of a list, which also belongs to return.
The reward is "what CTP said to me.".
Remember, the important thing to say three times, instruction and return, is the core content of CTP interface.
**Futures trading is full of orders and returns. **Our dialogue with the exchange is the return of orders and returns.
I told the exchange that I would buy two hands of ni2003 at the price limit, which is the order.
Then, the list is put on, and the exchange feeds back the information on the list to me, which is the return.
There's one deal, and the return is back.
I want to get rid of the rest and send the order to the exchange.
After the cancellation is successful, the exchange will send me the cancellation return.
......
And so on, again and again, this is the process of trading.
In addition, subscription, login, query It is also composed of instructions and returns.
Now you know enough about the importance of command and reward?
Common instructions and rewards
Instructions and returns are often in pairs. For example, the order connectMd connecting the market and the return onMdFrontConnected connecting the market are a pair. According to this rule, we will sort out the commonly used instructions and returns.
Type name Description
Command RegisterSpi and RegisterFront to connect to the quotation server
Return on frontconnected
Command ReqUserLogin to log in to quotation server
Return OnRspUserLogin market login return
Order SubscribeMarketData subscription Market
Return onrtndethmarketdata market push
Order UnSubscribeMarketData to unsubscribe (no return)
Return
instructions
Report error of onRspMdError (no instruction)
Order RegisterSpi and RegisterFront to connect to the transaction server
Return on frontconnected transaction connection return
Command GetTradingDay to get the current trading day (directly return the trading day value, no return)
Return
Instruction ReqAuthenticate requests client authentication
Return OnRspAuthenticate client authentication return
Instruct ReqUserLogin to log in to the transaction server
Return OnRspUserLogin transaction login return
Instruction ReqUserLogout log out of transaction server
Return OnRspUserLogout transaction logout return
Order reqsettlementifconfirm confirmation of investor settlement results
Return OnRspSettlementInfoConfirm
Instruction ReqQryInstrument query contract
Return OnRspQryInstrument query contract return
Instruction ReqQryOrder query entry
Report OnRspQryOrder query report report
Instruction ReqQryInvestorPosition query position
Return OnRspQryInvestorPosition query position return
Instruct ReqQryTradingAccount to query fund account
Return OnRspQryTradingAccount query fund account return
Instruct ReqQryInstrumentMarginRate to query the contract margin rate
Return OnRspQryInstrumentMarginRate query contract margin rate return
Order ReqQryInstrumentCommissionRate to query contract handling rate
Return onrspqryinstrument commissionrate query contract handling rate return
Command ReqQrySettlementInfo to query settlement doc
Return OnRspQrySettlementInfo query statement return
Command ReqQryProduct query product
Return OnRspQryProduct query product return
Order ReqQryTrade to query transaction
Return OnRspQryTrade query transaction return
Order ReqQryInvestorPositionDetail to query investor position details
Return OnRspQryInvestorPositionDetail query position detail return
Order ReqQryInvestor to query investors
Return OnRspQryInvestor query investor return
Instruction ReqOrderInsert, ReqOrderAction entry, cancellation
Return OnRtnOrder return or cancellation return (depending on the parameter to distinguish the return type)
Report on the rejection of OnRspOrderInsert by the front-end machine
Return return on the rejection of the OnErrRtnOrderInsert entry by the exchange
Report OnRspOrderAction return of cancellation rejected by the front-end machine
Return the return of the order cancellation rejected by the exchange
Return OnRtnTrade transaction return
instructions
Report OnRspTdError transaction error (no instruction)
It can be seen that most instruction functions start with "Req" and return functions start with "On".
Remember this "naming subterfuge", when you read C + + code, it's easy to distinguish between instructions and returns.
And then, how did the order go out? How does the return come to our computer from the exchange?
More specifically, how are instructions transferred from C to C + +? How is the return transferred from C + + to C?
Now let's look at these questions.
Instruction flow
Take the order to connect the market as an example.
The functions in C are:
///Location of dll output by C + + const string dllPath = @"CTP_se.dll"; ///Refer to the function "U connectMd" in C + + [DllImport(dllPath, EntryPoint = "_connectMd")] ///The function in C ා, the "extern" label determines that it should refer to the function "﹖ connectMd" in C + + according to the previous sentence static extern int ConnectMd( char[] pszFrontAddress //Quotation server address (string, required) ); public int connectMd(string tryingMdAdd) { return ConnectMd(tryingMdAdd.ToCharArray()); }
The main functions in C + + are:
int connectMd(char *pszFrontAddress) { string str(pszFrontAddress); logWithTime("Already exist" + toStr(mdClientsN) + "When there are users, there are new users trying to connect with the market" + str); MDSPI* mdProxy = new MDSPI(); mdProxy->clientI = mdClientsN; mdSPIs.push_back(mdProxy); CThostFtdcMdApi* mdApi = CThostFtdcMdApi::CreateFtdcMdApi(); mdAPIs.push_back(mdApi); mdClientsN++; log("mdClientsN = " + toStr(mdClientsN)); mdApi->RegisterSpi((CThostFtdcMdSpi*)mdProxy); log("RegisterMdSpi"); mdApi->RegisterFront(pszFrontAddress); logWithTime("RegisterFront(Registered market address)" + str + "Complete"); mdApi->Init(); logWithTime("Init(Initialization) complete"); logWithTime("Assign a sequence number to it" + toStr(mdClientsN - 1)); return mdClientsN - 1; } CTP_API int __stdcall _connectMd(char *pszFrontAddress) { return connectMd(pszFrontAddress); }
Please understand that there is no relevant massive code posted here, but the students who are familiar with C + + may know the construction of this C + + project. If you really need to communicate, please contact me. Wechat has been written before.
Here is only an example of the market connection instruction. The flow of other instructions is similar to this. Please draw inferences from one example to understand.
Return process
The payoff can be more cumbersome than the instruction.
When we just wrote the instruction, it was very simple, just like a needle - C ා - find the function in C + + directly and call it.
But return can't simply call functions along the process. The process of return is to find C + + first and then C ා. We can't let C + + call C ා, because there is no such syntax.
For example, the market connection returns. When it comes, first go to thostmduserapi_se.dll, which is the official interface of the last issue. It's the "undercover agent" sent by the official to our computer. If the official news comes, of course, first look for it.
Then, it passes the message to C ා as an interface application program to do something after receiving the message.
Is it that simple? You must be dreaming.
First of all, news can't jump directly from the official dll to our C, because we can't modify the official dll.
Then it has to go through an intermediary, our self-made dll, a C + + version of dll. We usually name it "CTP.dll" (not only me, many developers name this intermediary), which is a translation, responsible for the communication between the official dll and our c program..
There is no obstacle for the official DLL to talk with CTP.dll. The rest of the problem lies in how to talk with C. His native language is C + +, he knows C Chen, so he can be the translator.
How does he know C Chen?
I'll put the conclusion here in advance and then say the reason. The conclusion is that CTP.dll can find the memory address of a function of C ා, so as to activate the function when something needs to be done. In this way, the message of C + + can remote control a certain action of C ා, which is also a translation, not that a C + + program can directly read C ා.
Memory address, which is the key word.
Hold on to this key word, let's understand the following process.
Take market linking returns for example.
Return comes to our computer, first find the official CTP provided thostmduserapi ﹣ se.dll, then find our own CTP.dll (both of which are C + +), call the return processing function "OnFrontConnected".
void CTP_API MDSPI::OnFrontConnected() { if (toDoOnMdFrontConnected != NULL) toDoOnMdFrontConnected(MDSPI::clientI); }
That is to say, when the market connection returns come to this machine, we need to do this: if the "to do on MD front connected" thing is not empty, call it.
So what is "to do on MD front connected"?
It is a function pointer.
Where does it point?
Point to a function to be executed by the interface program after receiving the quote connection return. This function is written in the interface program:
void onMdFrontConnected(int clientI) { //...... }
Let's ignore what the ellipsis means (what to do after receiving the market return), first solve the problem: how to make C + + remote control the thing to be done in C ා.
To tell C + + the memory address of this function, that is, register the pointer of this function in C + +:
CTP_API void WINAPI registerOnMdFrontConnected(ToDoOnMdFrontConnected callback) { toDoOnMdFrontConnected = callback; }
This is the action of registering function pointer. The "callback" in it is the function pointer from C ා and "toDoOnMdFrontConnected" is the record of C + + for this function pointer.
This "registerOnMdFrontConnected" is a C + + instruction, which is easy for C to call. C ා calling it is actually to tell C + + the function pointer, specifically:
1. First, create an agent for the above function onMdFrontConnected in C ා, because it can't transfer the memory address to C + +, only the agent can.
2.C calls the C + + function registerOnMdFrontConnected, and the parameter is the above agent. In this way, the memory address of the function onMdFrontConnected is passed to C + +.
Then, when C + + receives the exchange message, it executes OnFrontConnected. When it finds that toDoOnMdFrontConnected is not empty, it executes toDoOnMdFrontConnected, which is actually a pointer to the C ා function onMdFrontConnected, so it executes the C ා.
In this way, the scene of C + + remote control is magically realized.
Therefore, when we receive the message from the exchange, we need to record the database and correct the records. We need to withdraw the old order and open a new warehouse. We need to detect the programmed strategy. When we need to do this, we need not bother C + +, and we can write it in the familiar C language.
Therefore, our trading software is no longer a cold black DOS window, but can be——