diff --git a/AmibrokerFeeder/RTDMan/Now_h.h b/AmibrokerFeeder/RTDMan/Now_h.h new file mode 100644 index 0000000..81816b5 --- /dev/null +++ b/AmibrokerFeeder/RTDMan/Now_h.h @@ -0,0 +1,668 @@ + + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 7.00.0555 */ +/* at Mon May 09 12:25:43 2016 + */ +/* Compiler settings for include\Now.IDL: + Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 7.00.0555 + protocol : dce , ms_ext, c_ext, robust + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: + __declspec(uuid()), __declspec(selectany), __declspec(novtable) + DECLSPEC_UUID(), MIDL_INTERFACE() +*/ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 475 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif // __RPCNDR_H_VERSION__ + + +#ifndef __Now_h_h__ +#define __Now_h_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifndef __IScripRTD_FWD_DEFINED__ +#define __IScripRTD_FWD_DEFINED__ +typedef interface IScripRTD IScripRTD; +#endif /* __IScripRTD_FWD_DEFINED__ */ + + +#ifndef __IRTDUpdateEvent_FWD_DEFINED__ +#define __IRTDUpdateEvent_FWD_DEFINED__ +typedef interface IRTDUpdateEvent IRTDUpdateEvent; +#endif /* __IRTDUpdateEvent_FWD_DEFINED__ */ + + +#ifndef __IPlusapi_FWD_DEFINED__ +#define __IPlusapi_FWD_DEFINED__ +typedef interface IPlusapi IPlusapi; +#endif /* __IPlusapi_FWD_DEFINED__ */ + + +#ifndef __ScripRTD_FWD_DEFINED__ +#define __ScripRTD_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class ScripRTD ScripRTD; +#else +typedef struct ScripRTD ScripRTD; +#endif /* __cplusplus */ + +#endif /* __ScripRTD_FWD_DEFINED__ */ + + +#ifndef __Plusapi_FWD_DEFINED__ +#define __Plusapi_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class Plusapi Plusapi; +#else +typedef struct Plusapi Plusapi; +#endif /* __cplusplus */ + +#endif /* __Plusapi_FWD_DEFINED__ */ + + +#ifdef __cplusplus +extern "C"{ +#endif + + + +#ifndef __NESTClientLib_LIBRARY_DEFINED__ +#define __NESTClientLib_LIBRARY_DEFINED__ + +/* library NESTClientLib */ +/* [custom][custom][custom][helpstring][version][uuid] */ + + + + + +EXTERN_C const IID LIBID_NESTClientLib; + +#ifndef __IScripRTD_INTERFACE_DEFINED__ +#define __IScripRTD_INTERFACE_DEFINED__ + +/* interface IScripRTD */ +/* [object][oleautomation][nonextensible][dual][helpstring][uuid] */ + + +EXTERN_C const IID IID_IScripRTD; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("EC0E6191-DB51-11D3-8F3E-00C04F3651B8") + IScripRTD : public IDispatch + { + public: + virtual /* [id] */ HRESULT STDMETHODCALLTYPE ServerStart( + /* [in] */ IRTDUpdateEvent *callback, + /* [retval][out] */ long *result) = 0; + + virtual /* [id] */ HRESULT STDMETHODCALLTYPE ConnectData( + /* [in] */ long topicId, + /* [in] */ SAFEARRAY * *strings, + /* [out][in] */ VARIANT_BOOL *newValues, + /* [retval][out] */ VARIANT *values) = 0; + + virtual /* [id] */ HRESULT STDMETHODCALLTYPE RefreshData( + /* [out][in] */ long *topicCount, + /* [retval][out] */ SAFEARRAY * *data) = 0; + + virtual /* [id] */ HRESULT STDMETHODCALLTYPE DisconnectData( + /* [in] */ long topicId) = 0; + + virtual /* [id] */ HRESULT STDMETHODCALLTYPE Heartbeat( + /* [retval][out] */ long *result) = 0; + + virtual /* [id] */ HRESULT STDMETHODCALLTYPE ServerTerminate( void) = 0; + + }; + +#else /* C style interface */ + + typedef struct IScripRTDVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IScripRTD * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + __RPC__deref_out void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IScripRTD * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IScripRTD * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IScripRTD * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IScripRTD * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IScripRTD * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [range][in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IScripRTD * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [id] */ HRESULT ( STDMETHODCALLTYPE *ServerStart )( + IScripRTD * This, + /* [in] */ IRTDUpdateEvent *callback, + /* [retval][out] */ long *result); + + /* [id] */ HRESULT ( STDMETHODCALLTYPE *ConnectData )( + IScripRTD * This, + /* [in] */ long topicId, + /* [in] */ SAFEARRAY * *strings, + /* [out][in] */ VARIANT_BOOL *newValues, + /* [retval][out] */ VARIANT *values); + + /* [id] */ HRESULT ( STDMETHODCALLTYPE *RefreshData )( + IScripRTD * This, + /* [out][in] */ long *topicCount, + /* [retval][out] */ SAFEARRAY * *data); + + /* [id] */ HRESULT ( STDMETHODCALLTYPE *DisconnectData )( + IScripRTD * This, + /* [in] */ long topicId); + + /* [id] */ HRESULT ( STDMETHODCALLTYPE *Heartbeat )( + IScripRTD * This, + /* [retval][out] */ long *result); + + /* [id] */ HRESULT ( STDMETHODCALLTYPE *ServerTerminate )( + IScripRTD * This); + + END_INTERFACE + } IScripRTDVtbl; + + interface IScripRTD + { + CONST_VTBL struct IScripRTDVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IScripRTD_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IScripRTD_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IScripRTD_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IScripRTD_GetTypeInfoCount(This,pctinfo) \ + ( (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) ) + +#define IScripRTD_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + ( (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) ) + +#define IScripRTD_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + ( (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) ) + +#define IScripRTD_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + ( (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) ) + + +#define IScripRTD_ServerStart(This,callback,result) \ + ( (This)->lpVtbl -> ServerStart(This,callback,result) ) + +#define IScripRTD_ConnectData(This,topicId,strings,newValues,values) \ + ( (This)->lpVtbl -> ConnectData(This,topicId,strings,newValues,values) ) + +#define IScripRTD_RefreshData(This,topicCount,data) \ + ( (This)->lpVtbl -> RefreshData(This,topicCount,data) ) + +#define IScripRTD_DisconnectData(This,topicId) \ + ( (This)->lpVtbl -> DisconnectData(This,topicId) ) + +#define IScripRTD_Heartbeat(This,result) \ + ( (This)->lpVtbl -> Heartbeat(This,result) ) + +#define IScripRTD_ServerTerminate(This) \ + ( (This)->lpVtbl -> ServerTerminate(This) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IScripRTD_INTERFACE_DEFINED__ */ + + +#ifndef __IRTDUpdateEvent_INTERFACE_DEFINED__ +#define __IRTDUpdateEvent_INTERFACE_DEFINED__ + +/* interface IRTDUpdateEvent */ +/* [object][oleautomation][dual][uuid] */ + + +EXTERN_C const IID IID_IRTDUpdateEvent; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("A43788C1-D91B-11D3-8F39-00C04F3651B8") + IRTDUpdateEvent : public IDispatch + { + public: + virtual /* [id] */ HRESULT STDMETHODCALLTYPE UpdateNotify( void) = 0; + + virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_HeartbeatInterval( + /* [retval][out] */ long *value) = 0; + + virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_HeartbeatInterval( + /* [in] */ long value) = 0; + + virtual /* [id] */ HRESULT STDMETHODCALLTYPE Disconnect( void) = 0; + + }; + +#else /* C style interface */ + + typedef struct IRTDUpdateEventVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IRTDUpdateEvent * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + __RPC__deref_out void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IRTDUpdateEvent * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IRTDUpdateEvent * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IRTDUpdateEvent * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IRTDUpdateEvent * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IRTDUpdateEvent * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [range][in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IRTDUpdateEvent * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [id] */ HRESULT ( STDMETHODCALLTYPE *UpdateNotify )( + IRTDUpdateEvent * This); + + /* [propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_HeartbeatInterval )( + IRTDUpdateEvent * This, + /* [retval][out] */ long *value); + + /* [propput][id] */ HRESULT ( STDMETHODCALLTYPE *put_HeartbeatInterval )( + IRTDUpdateEvent * This, + /* [in] */ long value); + + /* [id] */ HRESULT ( STDMETHODCALLTYPE *Disconnect )( + IRTDUpdateEvent * This); + + END_INTERFACE + } IRTDUpdateEventVtbl; + + interface IRTDUpdateEvent + { + CONST_VTBL struct IRTDUpdateEventVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IRTDUpdateEvent_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IRTDUpdateEvent_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IRTDUpdateEvent_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IRTDUpdateEvent_GetTypeInfoCount(This,pctinfo) \ + ( (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) ) + +#define IRTDUpdateEvent_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + ( (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) ) + +#define IRTDUpdateEvent_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + ( (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) ) + +#define IRTDUpdateEvent_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + ( (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) ) + + +#define IRTDUpdateEvent_UpdateNotify(This) \ + ( (This)->lpVtbl -> UpdateNotify(This) ) + +#define IRTDUpdateEvent_get_HeartbeatInterval(This,value) \ + ( (This)->lpVtbl -> get_HeartbeatInterval(This,value) ) + +#define IRTDUpdateEvent_put_HeartbeatInterval(This,value) \ + ( (This)->lpVtbl -> put_HeartbeatInterval(This,value) ) + +#define IRTDUpdateEvent_Disconnect(This) \ + ( (This)->lpVtbl -> Disconnect(This) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IRTDUpdateEvent_INTERFACE_DEFINED__ */ + + +#ifndef __IPlusapi_INTERFACE_DEFINED__ +#define __IPlusapi_INTERFACE_DEFINED__ + +/* interface IPlusapi */ +/* [object][oleautomation][nonextensible][dual][helpstring][uuid] */ + + +EXTERN_C const IID IID_IPlusapi; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5C07F918-033B-4B72-8B6A-F1DB173CE8B1") + IPlusapi : public IDispatch + { + public: + virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE PlaceOrder( + /* [in] */ BSTR bsTransType, + /* [in] */ BSTR bsUniqueRefNo, + /* [in] */ BSTR bsExchange, + /* [in] */ BSTR bsTradingSymbol, + /* [in] */ BSTR bsValidity, + /* [in] */ BSTR bsOrderType, + /* [in] */ long lQty, + /* [in] */ double dPrice, + /* [in] */ double dTriggerPrice, + /* [in] */ long lDiscQty, + /* [in] */ BSTR bsProductType, + /* [in] */ BSTR bsClientID) = 0; + + virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE ModifyOrder( + /* [in] */ BSTR bsOrderRefNo, + /* [in] */ BSTR bsValidity, + /* [in] */ BSTR bsOrderType, + /* [in] */ long lQty, + /* [in] */ double dPrice, + /* [in] */ double dTriggerPrice, + /* [in] */ long lDiscQty) = 0; + + virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE CancelOrder( + /* [in] */ BSTR bsOrderRefNum) = 0; + + virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE SetObjectName( + /* [in] */ BSTR bsObjectName) = 0; + + virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE GetOrderStatus( + /* [in] */ BSTR bsOrderRefNo, + /* [out] */ BSTR *bsStatus, + /* [out] */ long *lFillQty, + /* [out] */ double *dFillPrice) = 0; + + virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE GetPlusVersion( + /* [out] */ BSTR *bsVersion) = 0; + + }; + +#else /* C style interface */ + + typedef struct IPlusapiVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IPlusapi * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + __RPC__deref_out void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IPlusapi * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IPlusapi * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IPlusapi * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IPlusapi * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IPlusapi * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [range][in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IPlusapi * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *PlaceOrder )( + IPlusapi * This, + /* [in] */ BSTR bsTransType, + /* [in] */ BSTR bsUniqueRefNo, + /* [in] */ BSTR bsExchange, + /* [in] */ BSTR bsTradingSymbol, + /* [in] */ BSTR bsValidity, + /* [in] */ BSTR bsOrderType, + /* [in] */ long lQty, + /* [in] */ double dPrice, + /* [in] */ double dTriggerPrice, + /* [in] */ long lDiscQty, + /* [in] */ BSTR bsProductType, + /* [in] */ BSTR bsClientID); + + /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *ModifyOrder )( + IPlusapi * This, + /* [in] */ BSTR bsOrderRefNo, + /* [in] */ BSTR bsValidity, + /* [in] */ BSTR bsOrderType, + /* [in] */ long lQty, + /* [in] */ double dPrice, + /* [in] */ double dTriggerPrice, + /* [in] */ long lDiscQty); + + /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *CancelOrder )( + IPlusapi * This, + /* [in] */ BSTR bsOrderRefNum); + + /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *SetObjectName )( + IPlusapi * This, + /* [in] */ BSTR bsObjectName); + + /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *GetOrderStatus )( + IPlusapi * This, + /* [in] */ BSTR bsOrderRefNo, + /* [out] */ BSTR *bsStatus, + /* [out] */ long *lFillQty, + /* [out] */ double *dFillPrice); + + /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *GetPlusVersion )( + IPlusapi * This, + /* [out] */ BSTR *bsVersion); + + END_INTERFACE + } IPlusapiVtbl; + + interface IPlusapi + { + CONST_VTBL struct IPlusapiVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IPlusapi_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IPlusapi_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IPlusapi_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IPlusapi_GetTypeInfoCount(This,pctinfo) \ + ( (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) ) + +#define IPlusapi_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + ( (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) ) + +#define IPlusapi_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + ( (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) ) + +#define IPlusapi_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + ( (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) ) + + +#define IPlusapi_PlaceOrder(This,bsTransType,bsUniqueRefNo,bsExchange,bsTradingSymbol,bsValidity,bsOrderType,lQty,dPrice,dTriggerPrice,lDiscQty,bsProductType,bsClientID) \ + ( (This)->lpVtbl -> PlaceOrder(This,bsTransType,bsUniqueRefNo,bsExchange,bsTradingSymbol,bsValidity,bsOrderType,lQty,dPrice,dTriggerPrice,lDiscQty,bsProductType,bsClientID) ) + +#define IPlusapi_ModifyOrder(This,bsOrderRefNo,bsValidity,bsOrderType,lQty,dPrice,dTriggerPrice,lDiscQty) \ + ( (This)->lpVtbl -> ModifyOrder(This,bsOrderRefNo,bsValidity,bsOrderType,lQty,dPrice,dTriggerPrice,lDiscQty) ) + +#define IPlusapi_CancelOrder(This,bsOrderRefNum) \ + ( (This)->lpVtbl -> CancelOrder(This,bsOrderRefNum) ) + +#define IPlusapi_SetObjectName(This,bsObjectName) \ + ( (This)->lpVtbl -> SetObjectName(This,bsObjectName) ) + +#define IPlusapi_GetOrderStatus(This,bsOrderRefNo,bsStatus,lFillQty,dFillPrice) \ + ( (This)->lpVtbl -> GetOrderStatus(This,bsOrderRefNo,bsStatus,lFillQty,dFillPrice) ) + +#define IPlusapi_GetPlusVersion(This,bsVersion) \ + ( (This)->lpVtbl -> GetPlusVersion(This,bsVersion) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IPlusapi_INTERFACE_DEFINED__ */ + + +EXTERN_C const CLSID CLSID_ScripRTD; + +#ifdef __cplusplus + +class DECLSPEC_UUID("A04A3240-D051-4B4C-B004-CA92151F11E5") +ScripRTD; +#endif + +EXTERN_C const CLSID CLSID_Plusapi; + +#ifdef __cplusplus + +class DECLSPEC_UUID("91741D4F-948B-46A0-A2CC-0B925C4F5E17") +Plusapi; +#endif +#endif /* __NESTClientLib_LIBRARY_DEFINED__ */ + +/* Additional Prototypes for ALL interfaces */ + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/AmibrokerFeeder/RTDMan/Now_i.c b/AmibrokerFeeder/RTDMan/Now_i.c new file mode 100644 index 0000000..086ff78 --- /dev/null +++ b/AmibrokerFeeder/RTDMan/Now_i.c @@ -0,0 +1,94 @@ + + +/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */ + +/* link this file in with the server and any clients */ + + + /* File created by MIDL compiler version 7.00.0555 */ +/* at Mon May 09 12:25:43 2016 + */ +/* Compiler settings for include\Now.IDL: + Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 7.00.0555 + protocol : dce , ms_ext, c_ext, robust + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: + __declspec(uuid()), __declspec(selectany), __declspec(novtable) + DECLSPEC_UUID(), MIDL_INTERFACE() +*/ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +#ifdef __cplusplus +extern "C"{ +#endif + + +#include +#include + +#ifdef _MIDL_USE_GUIDDEF_ + +#ifndef INITGUID +#define INITGUID +#include +#undef INITGUID +#else +#include +#endif + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) + +#else // !_MIDL_USE_GUIDDEF_ + +#ifndef __IID_DEFINED__ +#define __IID_DEFINED__ + +typedef struct _IID +{ + unsigned long x; + unsigned short s1; + unsigned short s2; + unsigned char c[8]; +} IID; + +#endif // __IID_DEFINED__ + +#ifndef CLSID_DEFINED +#define CLSID_DEFINED +typedef IID CLSID; +#endif // CLSID_DEFINED + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} + +#endif !_MIDL_USE_GUIDDEF_ + +MIDL_DEFINE_GUID(IID, LIBID_NESTClientLib,0xD2F45C54,0xF024,0x4D5B,0xB0,0x48,0x04,0x5D,0x62,0xB6,0x8F,0x59); + + +MIDL_DEFINE_GUID(IID, IID_IScripRTD,0xEC0E6191,0xDB51,0x11D3,0x8F,0x3E,0x00,0xC0,0x4F,0x36,0x51,0xB8); + + +MIDL_DEFINE_GUID(IID, IID_IRTDUpdateEvent,0xA43788C1,0xD91B,0x11D3,0x8F,0x39,0x00,0xC0,0x4F,0x36,0x51,0xB8); + + +MIDL_DEFINE_GUID(IID, IID_IPlusapi,0x5C07F918,0x033B,0x4B72,0x8B,0x6A,0xF1,0xDB,0x17,0x3C,0xE8,0xB1); + + +MIDL_DEFINE_GUID(CLSID, CLSID_ScripRTD,0xA04A3240,0xD051,0x4B4C,0xB0,0x04,0xCA,0x92,0x15,0x1F,0x11,0xE5); + + +MIDL_DEFINE_GUID(CLSID, CLSID_Plusapi,0x91741D4F,0x948B,0x46A0,0xA2,0xCC,0x0B,0x92,0x5C,0x4F,0x5E,0x17); + +#undef MIDL_DEFINE_GUID + +#ifdef __cplusplus +} +#endif + + + diff --git a/AmibrokerFeeder/RTDMan/RTDMan.ini b/AmibrokerFeeder/RTDMan/RTDMan.ini index 82c1b7a..135542c 100644 --- a/AmibrokerFeeder/RTDMan/RTDMan.ini +++ b/AmibrokerFeeder/RTDMan/RTDMan.ini @@ -1,5 +1,6 @@ -[RTDMan] +; DONT CHANGE ANYTHING IN THIS!!!!!!!!!!!! ----------------->>>>>>>>> IF YOU DONT KNOW WHAT IT IS! +[RTDMan] ; README ; ; A) For All Folder Paths, @@ -16,50 +17,70 @@ ; "LTT" / "Last Traded Price" = LTT Field ID ; Use NOW.ScripRTD for NOW / Nest.ScripRTD for Nest -RTDServerProgID=NOW.ScripRTD +RTDServerProgID=Nest.ScripRTD -; Period before bar data sent to Amibroker - In milliseconds - Minimum 1 second -BarPeriod=1000 +; CSV Folder Path - Prefer Ram drive +CSVFolderPath=R:/rtd/ +;Client=AB +Client=NT -; CSV Folder Path - Prefer Ram drive. End with / -CSVFolderPath=R:/rtd/ +; Amibroker DB Path - Default one will be used by Amibroker if empty. set only if needed. +;AbDbPath=D:/temp/AmibrokerDB_/ -; Save 1 csv for each Scrip with name = alias.csv inside CSVFolderPath -; Can be used for backfill -Archive=true +;Keep BarPeriod - 1000 for 1 sec candles and 60000 for 1 min. candles. +BarPeriod=0 -; No of BarPeriod to wait before ringing bell (Once) if RTD becomes inactive. -; Set as 0 to disable -BellWaitTime=25 +;Refresh Period in millisonds is for pushing data to Ami or NT. +;This should not be less than 50 or more than 1000(1 second) +RefreshPeriod=250 -; Define Open/Close minutes. Quotes outside it will be ignored. Also Bell wont ring outside market hours. -OpenTime = 09:15:00 -CloseTime = 15:29:59 +; ReuqestRefresh should be 1 for Amibroker version 5.3 or below +;else charts will not be refreshed +RequestRefresh=0 -; Set Target Client. "AB" (Default) to push prices to Amibroker. "NT" for NinjaTrader -Client=AB +; No of BarPeriod to wait before ringing bell if RTD becomes inactive. +; Set as 0 to disable +BellWaitTime=15 +;-------------------------------------------------------(For Developers Only) ------------------------ +; View Data received from RTD server in Terminal +; ViewTicData (as getting fields), ViewRawData (after filling all fields),ViewBarData(after processing) +; Set as 0 or null to disable +ViewTicData=0 +ViewRawData=0 +ViewBarData=0 -; Amibroker DB Path - Default one will be used by Amibroker if empty. set only if needed. -;AbDbPath=D:/temp/AmibrokerDB_/ +;Scrip Settings------------------------------------------------------------------------------- +;There should be no gap between successive lines +;You can use 'LTQ' (Nest) or 'Last Trade Qty' (NOW) or 'Volume Traded Today' for calculating volume. +;If 'Volume Traded Today' is used, (Volume = current-Vol_Traded - prev-Vol_Traded) +;You can use 'Volume Traded Today' for one scrip and LTQ for another. RTDMan will detect +;If 'LTQ' or 'Last Trade Qty' is used, (Volume = current-Vol + LTQ) for bar period. + +;Field after Open Interest is used for LTP Multiplier. This is used for Nifty spot pulled from Currency segment -; Only ScripX from here - No extra spaces in value -; Change Scrip Id and Field Ids if different. -; LTP Multiplier - Used for getting Indices in NOW. Default 1 if not specified ( keeps LTP same ) -; -; ScripX=ScripID(mandatory);Alias(Amibroker Scrip name-mandatory-Taken as-it-is);LTP Field ID(mandatory);LTT Field ID;Todays Volume Field ID;OI Field ID;LTP Multiplier +;Nifty spot is to be multiplied by 100. +;Bid Rate;Ask Rate; Bid Qty;Ask Qty; These are optional. They should be used strictly in pairs. +;Bid Qty;Ask Qty if used, they will be accumulated in respective fields for the bar period. +;i.e. Bid Qty = Bid Qty + Bid Qty for all tics during 1 second or 1 minute as the case may be. +;If Bid Rate;Ask Rate is not used, do not use Bid Qty;Ask Qty; Fields up to Oi will be pushed to Ami or NT +;Bid Rate;Ask Rate go to Ami in Aux1 and Aux2 respectively. +;If Bid Rate;Ask Rate is used but Bid Qty;Ask Qty; is not used, RTDMan will use volume to fill those fields. +; if (ltp - bid_rate) < (ask_rate - ltp) then bid_qty = volume; +; else ask_qty = volume; (hope bid_rate and ask_rate are not equal) +;If Bid_Qty and Ask_Qty is used, a new scrip will be created by appending 'e' to the ticker. +;For example, CrudeOil will have CrudeOile created for storing Bid_Qty and Ask_Qty. +;CrudeOile will have Date, Time, Close = LTP, H = Ask_rate, L = Bid_rate, V= Bid_Qty and OI = Ask_Qty -; NOW -;Scrip1=nse_fo|NIFTY15NOVFUT;NIFTY_F1;Last Traded Price;Last Trade Time;Volume Traded Today;; -Scrip1=cde_fo|NIFTY50;NIFTY;Last Traded Price;;;;100 -Scrip2=nse_cm|SBIN-EQ;SBIN;Last Traded Price;Last Trade Time;Volume Traded Today;; -Scrip3=nse_cm|TATASTEEL-EQ;TATASTEEL;Last Traded Price;Last Trade Time;Volume Traded Today;; -Scrip4=nse_cm|TATAMOTORS-EQ;TATAMOTORS;Last Traded Price;Last Trade Time;Volume Traded Today;; -Scrip5=nse_cm|AXISBANK-EQ;AXISBANK;Last Traded Price;Last Trade Time;Volume Traded Today;; -Scrip6=nse_cm|ICICIBANK-EQ;ICICIBANK;Last Traded Price;Last Trade Time;Volume Traded Today;; +;This part below should be used for scrips only. +Scrip1=mcx_fo|CRUDEOILM16APRFUT;CRUDEOILM;LTP;LTT;Volume Traded Today;Open Interest;;Bid Rate;Ask Rate;Bid Qty;Ask Qty; +Scrip2=mcx_fo|CRUDEOIL16APRFUT;CRUDEOIL;LTP;LTT;Volume Traded Today;Open Interest;;Bid Rate;Ask Rate;Bid Qty;Ask Qty; +Scrip3=mcx_fo|SILVERM16APRFUT;SILVERM16APRFUT;LTP;LTT;Volume Traded Today;Open Interest;;Bid Rate;Ask Rate;Bid Qty;Ask Qty; +Scrip4=nse_cm|AXISBANK-EQ;AXISBANK;LTP;LTT;Volume Traded Today;Open Interest;;Bid Rate;Ask Rate;Bid Qty;Ask Qty; +Scrip5=nse_fo|NIFTY16APRFUT;NIFTY16APRFUT;LTP;LTT;Volume Traded Today;Open Interest;;Bid Rate;Ask Rate;Bid Qty;Ask Qty; +Scrip6=nse_fo|BANKNIFTY16APRFUT;BANKNIFTY16APRFUT;LTP;LTT;Volume Traded Today;Open Interest;;Bid Rate;Ask Rate;Bid Qty;Ask Qty; +Scrip7=mcx_fo|COPPER16APRFUT;COPPER16APRFUT;LTP;LTT;Volume Traded Today;Open Interest;;Bid Rate;Ask Rate;Bid Qty;Ask Qty; +Scrip8=mcx_fo|SILVER16MAYFUT;SILVER16MAYFUT;LTP;LTT;Volume Traded Today;Open Interest;;Bid Rate;Ask Rate;Bid Qty;Ask Qty; +Scrip9=mcx_fo|SILVERMIC16APRFUT;SILVERMIC16APRFUT;LTP;LTT;Volume Traded Today;Open Interest;;Bid Rate;Ask Rate;Bid Qty;Ask Qty; -; NEST -;Scrip1=nse_fo|NIFTY15JULFUT;NIFTY_F1;LTP;LTT;Volume Traded Today;Open Interest -;Scrip2=CNX Nifty;NIFTY;Index Value;;;; -;Scrip3=mcx_sx|USDINRCUR;USDINR;LTP;LTT diff --git a/AmibrokerFeeder/RTDMan/RTDMan.vcxproj b/AmibrokerFeeder/RTDMan/RTDMan.vcxproj index cd5f5b2..d46900c 100644 --- a/AmibrokerFeeder/RTDMan/RTDMan.vcxproj +++ b/AmibrokerFeeder/RTDMan/RTDMan.vcxproj @@ -39,7 +39,7 @@ - false + true $(ProjectDir)\include;$(IncludePath) $(ProjectDir)\source;$(SourcePath) $(SolutionDir)$(Configuration)\RTDMan\ @@ -121,6 +121,7 @@ del *.bat + @@ -135,6 +136,7 @@ del *.bat $(ProjectDir)\include\%(Filename)_h.h $(ProjectDir)\source\%(Filename)_i.c + diff --git a/AmibrokerFeeder/RTDMan/RTDMan.vcxproj.filters b/AmibrokerFeeder/RTDMan/RTDMan.vcxproj.filters index 3ef64cd..1bad4d5 100644 --- a/AmibrokerFeeder/RTDMan/RTDMan.vcxproj.filters +++ b/AmibrokerFeeder/RTDMan/RTDMan.vcxproj.filters @@ -45,11 +45,17 @@ Header Files + + Header Files + Header Files + + Header Files + diff --git a/AmibrokerFeeder/RTDMan/RTDManback.ini b/AmibrokerFeeder/RTDMan/RTDManback.ini new file mode 100644 index 0000000..4f7eefd --- /dev/null +++ b/AmibrokerFeeder/RTDMan/RTDManback.ini @@ -0,0 +1,69 @@ +[RTDMan] + +; +README +; +; +A) For All Folder Paths, +; +1) Use forward slash(/) and End with / +; +2) Do not use Drive Root. Ex Use R:/rtd/ but not R:/ +; +; B) Take ScripId and Field IDs using "Link to Excel" in Nest ( Right click scrip in Market watch -> Link to Excel -> Selected Items ) +; +; Ex Nest - =RTD("Nest.ScripRTD",,"nse_fo|NIFTY14MARFUT","LTT") +; NOW - =RTD("NOW.ScripRTD",,"MktWatch","nse_cm|AXISBANK-EQ","Last Traded Price") +; +; Here, "Nest.ScripRTD" / "NOW.ScripRTD" = RTDServerProgID +; "nse_fo|NIFTY14MARFUT" / "nse_cm|AXISBANK-EQ" = ScripID +; "LTT" / "Last Traded Price" = LTT Field ID + +; Use NOW.ScripRTD for NOW / Nest.ScripRTD for Nest +RTDServerProgID=NOW.ScripRTD + +; Period before bar data sent to Amibroker - In milliseconds - Minimum 1 second +BarPeriod=1000 + +; CSV Folder Path - Prefer Ram drive. End with / +CSVFolderPath=R:/rtd/ + +; Save 1 csv for each Scrip with name = alias.csv inside CSVFolderPath +; Can be used for backfill +Archive=true + +; No of BarPeriod to wait before ringing bell (Once) if RTD becomes inactive. +; Set as 0 to disable +BellWaitTime=25 + +; Define Open/Close minutes. Quotes outside it will be ignored. Also Bell wont ring outside market hours. +OpenTime = 09:15:00 +CloseTime = 15:29:59 + +; Set Target Client. "AB" (Default) to push prices to Amibroker. "NT" for NinjaTrader +Client=AB + +; Amibroker DB Path - Default one will be used by Amibroker if empty. set only if needed. +;AbDbPath=D:/temp/AmibrokerDB_/ + +; Only ScripX from here - No extra spaces in value +; Change Scrip Id and Field Ids if different. +; LTP Multiplier - Used for getting Indices in NOW. Default 1 if not specified ( keeps LTP same ) +; +; ScripX=ScripID(mandatory);Alias(Amibroker Scrip name-mandatory-Taken as-it-is);LTP Field ID(mandatory);LTT Field ID;Todays Volume Field ID;OI Field ID;LTP Multiplier + +; NOW +;Scrip1=nse_fo|NIFTY15NOVFUT;NIFTY_F1;Last Traded Price;Last Trade Time;Volume Traded Today;; + +Scrip1=cde_fo|NIFTY50;NIFTY;Last Traded Price;;;;100 +Scrip2=nse_cm|SBIN-EQ;SBIN;Last Traded Price;Last Trade Time;Volume Traded Today;; +Scrip3=nse_cm|TATASTEEL-EQ;TATASTEEL;Last Traded Price;Last Trade Time;Volume Traded Today;; +Scrip4=nse_cm|TATAMOTORS-EQ;TATAMOTORS;Last Traded Price;Last Trade Time;Volume Traded Today;; +Scrip5=nse_cm|AXISBANK-EQ;AXISBANK;Last Traded Price;Last Trade Time;Volume Traded Today;; +Scrip6=nse_cm|ICICIBANK-EQ;ICICIBANK;Last Traded Price;Last Trade Time;Volume Traded Today;; + + +; NEST +;Scrip1=nse_fo|NIFTY15JULFUT;NIFTY_F1;LTP;LTT;Volume Traded Today;Open Interest +;Scrip2=CNX Nifty;NIFTY;Index Value;;;; +;Scrip3=mcx_sx|USDINRCUR;USDINR;LTP;LTT diff --git a/AmibrokerFeeder/RTDMan/include/ninja_trader.h b/AmibrokerFeeder/RTDMan/include/ninja_trader.h index a1a85b4..7e5ee37 100644 --- a/AmibrokerFeeder/RTDMan/include/ninja_trader.h +++ b/AmibrokerFeeder/RTDMan/include/ninja_trader.h @@ -9,14 +9,24 @@ class NinjaTrader{ private: HMODULE ninja_trader; - typedef int (__stdcall * Last_type) ( const char * instrument, double price, int size); + typedef int (__stdcall * Last_type) ( const char * instrument, double price, int size, const char * timestamp4); Last_type Last_ptr; + //Inserted Ask Bid by Boarders + typedef int (__stdcall * Ask_type) ( const char * instrument, double price, int size, const char * timestamp4); + Ask_type Ask_ptr; + typedef int (__stdcall * Bid_type) ( const char * instrument, double price, int size, const char * timestamp4); + Bid_type Bid_ptr; public: NinjaTrader(void); ~NinjaTrader(void); - int Last(std::string instrument, double price, int size); +// int Last(std::string instrument, double price, int size); removed by Boarders + //Inserted Ask Bid by Boarders + int LastPlayback(std::string instrument, double price, int size, std::string timestamp4); + int AskPlayback(std::string instrument, double price, int size, std::string timestamp4); + int BidPlayback(std::string instrument, double price, int size, std::string timestamp4); + }; #endif \ No newline at end of file diff --git a/AmibrokerFeeder/RTDMan/include/settings.h b/AmibrokerFeeder/RTDMan/include/settings.h index dd5bf7c..9083c59 100644 --- a/AmibrokerFeeder/RTDMan/include/settings.h +++ b/AmibrokerFeeder/RTDMan/include/settings.h @@ -11,7 +11,7 @@ class Settings{ bool isTargetNT(); // Is target Client NinjaTrader std::string rtd_server_prog_id; - int bar_period; // In milliseconds + int bar_period; // Used by Josh1 for candle forming int bell_wait_time; // No of bar_periods std::string csv_folder_path; // Folder in which we will save csv for AB and archived csv std::string csv_path; // path for csv file to be sent to Amibroker - Use ram drive @@ -22,6 +22,19 @@ class Settings{ std::string open_time; std::string close_time; +// Inserted by Josh1 ------------------------------------------------------------------------------------------ + int refresh_period; + short request_refresh; // for AmiBroker version 5.3 and below Inserted by Josh1 + short view_raw_data; // flag to view raw data + short view_bar_data; // flag to view bar data + short view_tic_data; // flag to view bar data + short view_NT_data; // flag to view bar data +// short view_AB_data; // flag to view bar data + + short use_ltq ; // Flag to use LTQ instead of Volume Traded Today + +//----------------------------------------------------------------------------------------------------------------- + struct Scrip { std::string topic_name; // Scrip Name = Topic 1 std::string ticker; // Ticker Alias sent to Amibroker @@ -29,7 +42,14 @@ class Settings{ std::string topic_LTT; std::string topic_vol_today; std::string topic_OI; - int ltp_multiplier; // Multiple LTP with this- Default 1 +// int ltp_multiplier; // Multiple LTP with this- Default 1 + double ltp_multiplier; // Changed by Josh1 + //Inserted by Josh1 + std::string topic_Ask_Rate; + std::string topic_Ask_Qty; + std::string topic_Bid_Rate; + std::string topic_Bid_Qty; + }; std::vector scrips_array; // RTD Topics for each scrip diff --git a/AmibrokerFeeder/RTDMan/include/worker.h b/AmibrokerFeeder/RTDMan/include/worker.h index e1b535a..6c39e6b 100644 --- a/AmibrokerFeeder/RTDMan/include/worker.h +++ b/AmibrokerFeeder/RTDMan/include/worker.h @@ -25,6 +25,7 @@ class Worker{ private: struct ScripBar; struct ScripState; // Forward Declare + struct RTData; // Forward Declare by Josh1 RTDClient *rtd_client; Amibroker *amibroker; @@ -35,7 +36,20 @@ class Worker{ ScripState *current, *previous; // Maintains Current and last state of each Scrip std::string today_date; // (in same order as Settings::Scrip::topic_name) std::ofstream csv_file_out; - + std::ofstream scrip_file_out; + + // Inserted by Josh1 ------------------------------------------------------------------------------ + std::string timestamp1; // (in same order as Settings::Scrip::topic_name) + std::string timestamp2; + std::string timestamp3; + std::string timestamp4; + + std::string cur_tm; // to store current time + int prev_field; // to keep track of previous field id + std::string bar_ltt; // Inserted by Josh1 - Purpose ????? + int records; // to keep track of records received from RTD feed + // End Inserted by Josh1 ------------------------------------------------------------------------------ + CRITICAL_SECTION lock; // Thread Data sync HANDLE Event_RTD_Update; // Signaled by RTD Callback HANDLE AB_timer; // Timer for AB poller @@ -51,6 +65,8 @@ class Worker{ void amibrokerPoller (); // Fetches Bar data and feeds to Amibroker void writeABCsv ( const std::vector & bars ); // This thread uses members - current , previous, settings void writeArchiveCsv ( const std::vector & bars ); // Archive Ticks in seperate csv. Used in backfill + void writeCurrentPrices( const std::stringstream & current_prices); // Write Current prices of all scrips + void pushToNT( const std::vector & bars ); // Push ticks to Ninjatrader void notifyActive (); void notifyInactive (); // Ring Bell if RTD Inactive @@ -59,13 +75,20 @@ class Worker{ Worker( const Worker& ); // Disable copy Worker operator=(const Worker& ); - // Used to create and resolve Topic ids + // Used to create and resolve Topic ids --------- order changed by Josh1 ------------- enum SCRIP_FIELDS{ // -- Topic 2 -- - LTP=0, // "LTP" + OI=0, // "Open Interest" LTT=1, // "LTT" VOLUME_TODAY=2, // "Volume Traded Today" - OI=3, // "Open Interest" - FIELD_COUNT=4 // No of Fields used + //Inserted by Josh1 + BID_RATE=3, // "Bid Rate" + ASK_RATE=4, // "Ask Rate" + BID_QTY=5, // "Bid Qty" + ASK_QTY=6, // "Ask Qty" + + LTP=7, // This topic should be last since + // Index has only "LTP" + FIELD_COUNT=8 // No of Fields used }; struct ScripState { double ltp; @@ -73,10 +96,18 @@ class Worker{ std::string last_bar_ltt; // last_bar_ltt will be always set with last sent bar's ltt long long vol_today; long long oi; - double bar_high; double bar_low; double bar_open; + + //Inserted by Josh1 ----------------------------------------------------------------------------------- + long volume; + double ask_rate; + long ask_qty; + double bid_rate; + long bid_qty; + short push; //Flag for data pushed to AB + //End Inserted by Josh1 ------------------------------------------------------------------------------- ScripState(); void reset(); @@ -96,11 +127,31 @@ class Worker{ double bar_high; double bar_low; double bar_close; - long long volume; + long volume; long long oi; + // Inserted by Josh1 + double ask_rate; + long ask_qty; + double bid_rate; + long bid_qty; }; -}; + //Structure RTData Inserted by Josh1 + struct RTData { + double ltp; + std::string ltt; // ltt can be empty for index scrips + long long vol_today; //to use as volume or LTQ now + long long oi; + long volume; + double ask_rate; + long ask_qty; + double bid_rate; + long bid_qty; + + RTData(); + void reset(); + }; +}; #endif \ No newline at end of file diff --git a/AmibrokerFeeder/RTDMan/source/ninja_trader.cpp b/AmibrokerFeeder/RTDMan/source/ninja_trader.cpp index 58dac7b..ffc28e4 100644 --- a/AmibrokerFeeder/RTDMan/source/ninja_trader.cpp +++ b/AmibrokerFeeder/RTDMan/source/ninja_trader.cpp @@ -11,10 +11,21 @@ NinjaTrader::NinjaTrader(void) : if( !ninja_trader ) throw( "Unable to load NTDirect.dll" ); - Last_ptr = (Last_type)GetProcAddress(ninja_trader, "Last"); + Last_ptr = (Last_type)GetProcAddress(ninja_trader, "LastPlayback"); + + //Inserted by Josh1 + Ask_ptr = (Ask_type)GetProcAddress(ninja_trader, "AskPlayback"); + Bid_ptr = (Bid_type)GetProcAddress(ninja_trader, "BidPlayback"); if( !Last_ptr ) throw( "Unable to load Last() from NTDirect.dll" ); + + //Inserted by Josh1 + if( !Ask_ptr) + throw( "Unable to load Ask() from NTDirect.dll" ); + if( !Bid_ptr) + throw( "Unable to load Bid() from NTDirect.dll" ); + } @@ -23,10 +34,35 @@ NinjaTrader::~NinjaTrader(void){ //FreeLibrary(ninja_trader); ninja_trader = NULL; Last_ptr = NULL; -} + //Inserted by Josh1 + Ask_ptr = NULL; + Bid_ptr = NULL; +} + +/***** Removed by Boarder int NinjaTrader::Last( std::string instrument, double price, int size ){ return Last_ptr( instrument.c_str(), price, size ); +} +****************End ********/ + +/************** Inserted by Boarder */ +int NinjaTrader::LastPlayback( std::string instrument, double price, int size , std::string timestamp4 ) +{ + + return Last_ptr( instrument.c_str(), price, size , timestamp4.c_str()); +} + +int NinjaTrader::AskPlayback( std::string instrument, double price, int size, std::string timestamp4 ) +{ + + return Ask_ptr( instrument.c_str(), price, size , timestamp4.c_str()); +} + +int NinjaTrader::BidPlayback( std::string instrument, double price, int size, std::string timestamp4 ) +{ + + return Bid_ptr( instrument.c_str(), price, size, timestamp4.c_str() ); } \ No newline at end of file diff --git a/AmibrokerFeeder/RTDMan/source/settings.cpp b/AmibrokerFeeder/RTDMan/source/settings.cpp index 9bbff45..67636a5 100644 --- a/AmibrokerFeeder/RTDMan/source/settings.cpp +++ b/AmibrokerFeeder/RTDMan/source/settings.cpp @@ -27,9 +27,28 @@ void Settings::loadSettings(){ std::string scrip_value; std::string scrip_key; +/* Removed by Josh1 ---------------------------------------------------------------------------------- if( bar_period < 1000 ){ // check $TICKMODE 1 throw "Minimum Bar Interval is 1000ms"; } +*/ + // added by Josh1 --------------------------------------------------------------------------- + request_refresh = getINIInt ("RequestRefresh"); + view_raw_data = getINIInt ("ViewRawData"); + view_bar_data = getINIInt ("ViewBarData"); + view_tic_data = getINIInt ("ViewTicData"); + view_NT_data = getINIInt ("ViewNTData"); +// view_AB_data = getINIInt ("ViewABData"); + refresh_period = getINIInt ("RefreshPeriod"); + + if( !( (bar_period == 0 ) || (bar_period == 1000 ) || (bar_period == 60000 )) ) { // check Barperiod + throw "Bar Period should be 0 or 1000 or 60000 "; + } + + if (refresh_period < 50 || refresh_period > 1000 ) { // Added by Josh1 + throw "Refresh period should be between 50 and 1000"; + } + // end added by Josh1 --------------------------------------------------------------------------- Util::createDirectory( csv_folder_path ); // If folder does not exist, create it csv_path = csv_folder_path + "abquotes.csv"; @@ -67,13 +86,30 @@ void Settings::loadSettings(){ if(split_strings.size() >=6 ){ scrip_topics.topic_OI = split_strings[5]; } - if(split_strings.size() >=7 && !split_strings[6].empty() ){ - scrip_topics.ltp_multiplier = std::stoi( split_strings[6] ); + if(split_strings.size() >=7 && !split_strings[6].empty() ){ +// scrip_topics.ltp_multiplier = std::stoi( split_strings[6] ); //Changed by Josh1 to double + scrip_topics.ltp_multiplier = std::stod( split_strings[6] ); } else { - scrip_topics.ltp_multiplier = 1; + scrip_topics.ltp_multiplier = 1.00; } + //Inserted by Boarders ---------------------- + if(split_strings.size() >=8 ){ + scrip_topics.topic_Bid_Rate = split_strings[7]; + } + if(split_strings.size() >=9 ){ + scrip_topics.topic_Ask_Rate = split_strings[8]; + } + if(split_strings.size() >=10 ){ + scrip_topics.topic_Bid_Qty = split_strings[9]; + } + if(split_strings.size() >=11 ){ + scrip_topics.topic_Ask_Qty = split_strings[10]; + } + + + scrips_array.push_back( scrip_topics ) ; no_of_scrips++; } diff --git a/AmibrokerFeeder/RTDMan/source/worker - Copy.cpp b/AmibrokerFeeder/RTDMan/source/worker - Copy.cpp new file mode 100644 index 0000000..42c46f5 --- /dev/null +++ b/AmibrokerFeeder/RTDMan/source/worker - Copy.cpp @@ -0,0 +1,697 @@ +/** + Copyright (C) 2014 SpiffSpaceman + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see +**/ + + +#include "worker.h" +#include "util.h" + +#include +#include +#include + +#include +#include + + +/** + * Read Scrips and setup DS. Start Timers and start AB thread + */ +Worker::Worker(): + is_rtd_started(false), + rtd_inactive_count(0), + amibroker(0), + ninja_trader(0) +{ + // _T() - character set Neutral + Event_RTD_Update = CreateEvent( NULL, false, FALSE, _T("RTD_UPDATE") );// Manual Reset = false - Event resets to nonsignaled on 1 wait release + Event_StopNow = CreateEvent( NULL, true, FALSE, NULL ); // Initialize state to FALSE. Read data only after callback + Event_Stopped = CreateEvent( NULL, true, FALSE, NULL ); + AB_timer = CreateWaitableTimer( NULL, false,NULL ); + + today_date = Util::getTime("%Y%m%d"); // Get todays date - yyyymmdd + + settings.loadSettings(); + + rtd_client = new RTDClient(); + current = new ScripState[ settings.no_of_scrips ] ; + previous = new ScripState[ settings.no_of_scrips ] ; + + for( int i=0 ; i::infinity()), bar_open(0), + push(0) // Push flag added by Josh1 +{} + +void Worker::ScripState::reset(){ + ltp = 0; vol_today = 0; oi =0; bar_high = 0; bar_low = std::numeric_limits::infinity(); bar_open = 0; ltt=""; last_bar_ltt=""; + push = 0; // Push flag added by Josh1 +} + +bool Worker::ScripState::operator==(const ScripState& right) const{ + return (ltp == right.ltp) && (vol_today == right.vol_today) && + (oi == right.oi ) && (bar_high == right.bar_high) && + (ltt == right.ltt) && (bar_low == right.bar_low ); +} + +//Inserted by Josh1 -------------------------------------------------------------------- +Worker::RTData::RTData() : + ltp(0), vol_today(0), oi(0),volume(0), ltt("") +{} + +void Worker::RTData::reset(){ + ltp = 0; vol_today = 0; oi =0; volume= 0; ltt.clear() ; +} +//end Inserted by Josh1 -------------------------------------------------------------------- + +/** + * Connect Topics + */ +void Worker::connect(){ + + rtd_client->initializeServer( settings.rtd_server_prog_id ); + rtd_client->startServer(); + + _beginthread( threadEntryDummy, 0, this ); // RTD Server ready. Start Amibroker Poller Thread + + for( int i=0 ; iconnectTopic(topic_id+LTP, topic_1, settings.scrips_array[i].topic_LTP ); + rtd_client->connectTopic(topic_id+LTT, topic_1, settings.scrips_array[i].topic_LTT ); + rtd_client->connectTopic(topic_id+VOLUME_TODAY, topic_1, settings.scrips_array[i].topic_vol_today ); + rtd_client->connectTopic(topic_id+OI, topic_1, settings.scrips_array[i].topic_OI ); + } +} + + +/** + * Wait for RTD Update event. On event, read new data and setup Current Bars + */ +void Worker::poll(){ + + while(1){ + if( WaitForSingleObject( Event_RTD_Update, INFINITE ) == WAIT_OBJECT_0 ){ + + std::map* data = rtd_client->readNewData() ; + if( data != 0 && !data->empty() ){ + processRTDData( data ); + } + delete data; + } + } +} + + +/** + * Read TopicId-Value data from COM and update Current Bar + **/ +void Worker::processRTDData( const std::map* data ){ + + //inserted by Josh1 ------------------------------------------------------------ + RTData newdata; + int prev_field = 999999999; + int notified = 0; + cur_tm = Util::getTime("%H"); // + //end inserted by Josh1 ------------------------------------------------------------ + + for( auto i=data->begin(), end=data->end() ; i!=end ; ++i ){ + + const long topic_id = i->first; + CComVariant topic_value = i->second; + + std::pair &ids = topic_id_to_scrip_field_map.at( topic_id ) ; + int script_id = ids.first; // Resolve Topic id to Scrip id and field + int field_id = ids.second; + +/********* Following code replaced by Josh1 with his code for two arrays current and previous ************************************************ + EnterCriticalSection( &lock ); // Lock when accessing current[] / previous[] + + switch( field_id ){ + case LTP :{ + double ltp = Util::getDouble( topic_value ) * settings.scrips_array[script_id].ltp_multiplier; + ScripState *_current = & current[script_id]; + + _current->ltp = ltp; + if( _current->bar_high < ltp ) _current->bar_high = ltp; + if( _current->bar_low > ltp ) _current->bar_low = ltp; + if( _current->bar_open == 0 ) _current->bar_open = ltp; + break ; + } + case VOLUME_TODAY :{ + long long vol_today = Util::getLong ( topic_value ); + current[script_id].vol_today = vol_today; + + if( vol_today !=0 && previous[script_id].vol_today == 0 ){ + previous[script_id].vol_today = vol_today; // On startup prev vol is 0, Set it so that we can get first bar volume + } + break ; + } + case LTT : current[script_id].ltt = Util::getString( topic_value ); break ; + case OI : current[script_id].oi = Util::getLong ( topic_value ); break ; + } + + LeaveCriticalSection( &lock ) ; +/********* End code replaced by Josh1 with his code for two arrays current and previous ************************************************/ +// Changes made by Josh1 **************************************************************************** + ScripState *_current = & current[script_id]; + ScripState *_previous = & previous[script_id]; + + switch( field_id ){ + case VOLUME_TODAY :{ + long long vol_today = Util::getLong ( topic_value ); + newdata.vol_today = vol_today; + break ; + } + case LTT : { + newdata.ltt = Util::getString( topic_value ); +/* -------------- Append milliseconds to LTT ------- Inserted by Josh1 ------------------ + SYSTEMTIME lt; + GetLocalTime(<); + std::stringstream stream; + stream <vol_today << " "; + std::cout << "OI - " <vol_today){ + newdata.reset(); //skip if there is no change in volume means no trade + continue; + } + break ; + } + } +/**********************************************************************************************************/ + if (settings.view_tic_data == 1){ + std::cout <<"\n"<< script_id << " - "; + std::cout << settings.scrips_array[script_id].topic_name << ", "; + std::cout << "LTT - " << newdata.ltt << ", "; + std::cout << "LTP - " << newdata.ltp << ", "; + std::cout << "Vol_today - " << newdata.vol_today << ", "; + std::cout << "OI - " <push == 1) { + *_previous = *_current; + } + else{ + previous[script_id].ltt = current[script_id].ltt; + previous[script_id].vol_today = _current->vol_today; + } + _current->vol_today = newdata.vol_today; +/* if( newdata.vol_today !=0 && previous[script_id].vol_today == 0 ){ + previous[script_id].vol_today = newdata.vol_today; // On startup prev vol is 0, Set it so that we can get first bar volume + }*/ + _current->bar_high = _current->bar_low = _current->bar_open = _current->ltp = newdata.ltp; + _current->ltt = newdata.ltt; + _current->oi = newdata.oi; +// _current->volume = newdata.vol_today - previous[script_id].vol_today; + _current->volume = newdata.vol_today; //Changed by Josh1 + + _current->push = 1; + newdata.reset(); + } + else { + _current->ltp = newdata.ltp; + _current->vol_today = newdata.vol_today; //removed by Josh1 25-3-16 + _current->oi = newdata.oi; + if( _current->bar_high < _current->ltp ) _current->bar_high = _current->ltp; + if( _current->bar_low > _current->ltp ) _current->bar_low = _current->ltp; +// _current->volume = _current->vol_today - previous[script_id].vol_today; //removed by Josh1 25-3-16 + _current->volume = _current->volume + newdata.vol_today; + _current->push = 1; + newdata.reset(); + } +/**********************************************************************************************************/ + if (settings.view_bar_data == 1){ + std::cout <<"\n"<< script_id << " - "; +// std::cout << settings.scrips_array[script_id].topic_name << " "; + std::cout << "LTT - " << _current->ltt << ", "; + std::cout << "LTP - " << _current->ltp << ", "; + std::cout << "Volume - " << _current->volume << ", "; + std::cout << "OI - " << _current->oi << ", "; + } +/**********************************************************************************************************/ + + LeaveCriticalSection( &lock ) ; + + } + prev_field = field_id; //Set previous field id + +//****** End Changes made by Josh1 ********************************************************************** + } +} + + +/** + * New Thread Entry Point + **/ +void Worker::threadEntryDummy(void* _this){ + ((Worker*)_this)->amibrokerPoller(); +} + +void Worker::amibrokerPoller(){ + + std::vector new_bars; + + if( settings.isTargetNT()){ + ninja_trader = new NinjaTrader(); + } + else{ + amibroker = new Amibroker( settings.ab_db_path, settings.csv_path, std::string("rtd.format") ); + } + // amibroker constructor has to be called in new thread + while(1){ + // Use events and timers instead of sleep which would be blocking + // Need to exit thread cleanly and immediately on application quit - sleep would block + + HANDLE events[] = {Event_StopNow,AB_timer}; // (A) Wait For Timer Event / Application Quit Event + DWORD return_code = WaitForMultipleObjects( 2, events , false, INFINITE ); + + if( return_code == WAIT_OBJECT_0 ){ // Quit Event + if(amibroker) + delete amibroker; amibroker = 0; + if(ninja_trader) + delete ninja_trader; ninja_trader = 0; + + SetEvent(Event_Stopped); + std::cout << "AB Feeder Thread Stopped" << std::endl; + return; + } + else if( return_code != WAIT_OBJECT_0 + 1 ){ // If not Timer Event, then we have some error + std::stringstream msg; msg << "WaitForSingleObject Failed - " << return_code; + throw( msg.str() ); + } + +/********* Following code replaced by Josh1 with his code for two arrays current and previous ************************************************ + // Shared data access start + EnterCriticalSection( &lock ); + + for( int i=0 ; ivol_today - _prev->vol_today ; + + // if( i==0) std::cout << i <<": " << *_current << std::endl ; + // If data not changed, skip + if( (_current->bar_open == 0) || // 1. No New data from readNewData() + (bar_volume==0 && _current->vol_today!=0) || // 2. Also skip if bar volume 0 but allow 0 volume scrips like forex + ((*_current) == (*_prev)) // 3. We got new data from readNewData() but its duplicate + ) continue; // NEST RTD sends all fields even if unconnected field (ex B/A) changes + + std::string bar_ltt; // Use ltt if present else use current time + !_current->ltt.empty() ? bar_ltt = _current->ltt : bar_ltt = Util::getTime( "%H:%M:%S" ); + + if( bar_ltt == _prev->last_bar_ltt ){ // IF LTT is same as previous LTT of this scrip ( but data is different ) + continue; // skip to avoid overwrite with same timestamp. + } // This can happen if we have more than 1 update in a second + // and poller took data in between. + if( bar_ltt == "15:29:59" && Util::getTime("%H") != "15" ){ // Skip 15:29:59 if current hour is not 15 + _current->reset(); // to avoid yesterdays quote on open in NOW. + _prev->reset(); // Reset Bars to avoid yesterday data in open bar + continue; + } + // Skip quotes outside market hours + if( !isMarketTime( bar_ltt )){ + _current->reset(); + _prev->reset(); + continue; + } + + new_bars.push_back( ScripBar() ); + ScripBar* bar = &new_bars.back(); + + bar->ltt = bar_ltt; + _current->last_bar_ltt = bar_ltt; + + _prev->vol_today !=0 ? bar->volume = bar_volume : bar->volume = 0; + // Ignore First bar volume as prev bar is not set. + bar->ticker = settings.scrips_array[i].ticker; // Otherwise, we get today's volume = First Bar volume + bar->bar_open = _current->bar_open; + bar->bar_high = _current->bar_high; + bar->bar_low = _current->bar_low; + bar->bar_close = _current->ltp; + bar->oi = _current->oi; + + (*_prev) = (*_current) ; // Copy current to previous and reset current + _current->reset(); + } + LeaveCriticalSection( &lock ); + // Shared data access end + + if( new_bars.empty() ){ // Notify if RTD inactive + notifyInactive(); + } + else{ // (C) Write to csv and Send to Amibroker + if( settings.isTargetNT()){ + pushToNT( new_bars ); + } + else{ + writeABCsv( new_bars ); + amibroker->import(); + } + + if( settings.is_archive ) + writeArchiveCsv( new_bars ); // Archive ticks to be used for backfill + } + new_bars.clear(); +/********* End code replaced by Josh1 with his code for two arrays current and previous ************************************************/ +// Changes made by Josh1 **************************************************************************** + + csv_file_out.open( settings.csv_path ); // Setup output stream to csv file + if( !csv_file_out.is_open() ){ // Reopening will also clear old content by default + throw( "Error opening file - " + settings.csv_path ); + } + + int records =0; + + for( int i=0 ; ipush == 1) { + if( settings.isTargetNT()){ + int volume = 0 ; + volume = (int)_prev->volume/4; // int should be atleast 4Bytes + + ninja_trader->Last( Scripname, _prev->bar_open, volume ); + ninja_trader->Last( Scripname, _prev->bar_high, volume ); + ninja_trader->Last( Scripname, _prev->bar_low, volume ); + ninja_trader->Last( Scripname, _prev->ltp, volume ); + } + else{ + csv_file_out << Scripname << ',' // $FORMAT Ticker, Date_YMD, Time, Open, High, + << today_date << ',' // Low, Close, Volume, OpenInt + << _prev->ltt << ',' + << _prev->bar_open << ',' + << _prev->bar_high << ',' + << _prev->bar_low << ',' + << _prev->ltp << ',' // ltp is close + << _prev->volume << ',' + << _prev->oi + << std::endl ; + } + _prev->push = 0; + records++; + } + + if (_current->push == 1) { + if( settings.isTargetNT()){ + int volume = 0 ; + volume = (int)_current->volume/4; // int should be atleast 4Bytes + + ninja_trader->Last( Scripname, _current->bar_open, volume ); + ninja_trader->Last( Scripname, _current->bar_high, volume ); + ninja_trader->Last( Scripname, _current->bar_low, volume ); + ninja_trader->Last( Scripname, _current->ltp, volume ); + } + else{ + csv_file_out << Scripname << ',' // $FORMAT Ticker, Date_YMD, Time, Open, High, + << today_date << ',' // Low, Close, Volume, OpenInt + << _current->ltt << ',' + << _current->bar_open << ',' + << _current->bar_high << ',' + << _current->bar_low << ',' + << _current->ltp << ',' // ltp is close + << _current->volume << ',' + << _current->oi + << std::endl ; + } + _current->push = 0; + records++; + } + + LeaveCriticalSection( &lock ); // Shared data access end + + } + + csv_file_out.close(); + if(records == 0){ + notifyInactive(); + } + amibroker->import(); + if(settings.request_refresh == 1){ // AmiBroker version 5.3 and below do not refresh automatically after import + amibroker->refreshAll(); + } + + } +} + +void Worker::notifyActive(){ + rtd_inactive_count = 0 ; + + if( !is_rtd_started ){ + is_rtd_started = true; + + std::cout << "RTD Active" << "\t\t\t\t\t\t\t" << "\r"; // Status in Console + std::flush(std::cout); + } +} +void Worker::notifyInactive(){ + + if( settings.bell_wait_time <= 0 ) + return; + + rtd_inactive_count++; + + if( rtd_inactive_count >= settings.bell_wait_time ){ // Wait time up? + + rtd_inactive_count = 0; + + std::cout << "RTD Inactive : " << Util::getTime() << "\r" ; // Status in Console + std::flush(std::cout); + + if( is_rtd_started ){ + is_rtd_started = false; // Play only Once + if( isMarketTime( Util::getTime() )) // and only in market hours + PlaySound( L"NotifyBell.wav" , NULL, SND_FILENAME | SND_ASYNC); + + } + } +} + +bool Worker::isMarketTime ( const std::string &time ){ // Time is in hh:mm:ss - lexicographical order. + return time >= settings.open_time && time <= settings.close_time ; // So string compare works +} + +void Worker::writeABCsv( const std::vector & bars ){ + + csv_file_out.open( settings.csv_path ); // Setup output stream to csv file + if( !csv_file_out.is_open() ){ // Reopening will also clear old content by default + throw( "Error opening file - " + settings.csv_path ); + } + + size_t size = bars.size(); + const ScripBar *bar; + + for( size_t i=0 ; iticker << ',' + << today_date << ',' + << bar->ltt << ',' + << bar->bar_open << ',' + << bar->bar_high << ',' + << bar->bar_low << ',' + << bar->bar_close << ',' + << bar->volume << ',' + << bar->oi << std::endl ; + } + + csv_file_out.close(); +} + +/* + Send OHLC to NinjaTrader + Workaround - Send OHLC as ticks with 1/4 volume +*/ +void Worker::pushToNT( const std::vector & bars ){ + + int volume = 0 ; + size_t size = bars.size(); + const ScripBar *bar; + + for( size_t i=0 ; ivolume/4; // int should be atleast 4Bytes + + ninja_trader->Last( bar->ticker, bar->bar_open, volume ); + ninja_trader->Last( bar->ticker, bar->bar_high, volume ); + ninja_trader->Last( bar->ticker, bar->bar_low, volume ); + ninja_trader->Last( bar->ticker, bar->bar_close, volume ); + } +} + +void Worker::writeArchiveCsv( const std::vector & bars ){ + + size_t size = bars.size(); + const ScripBar *bar; + std::string filename; + + for( size_t i=0 ; iticker ){ // Open new file stream for each ticker + + filename = bar->ticker; // Use Scrip Alias as filename + if( csv_file_out.is_open() ) + csv_file_out.close(); + // Open file for - write + append mode + csv_file_out.open( settings.csv_folder_path + filename + + ".csv", std::fstream::out | std::fstream::app ); + if( !csv_file_out.is_open() ){ + throw( "Error opening file - " + settings.csv_folder_path + filename + + ".csv" ); + } + } + + csv_file_out << bar->ticker << ',' + << today_date << ',' + << bar->ltt << ',' + << bar->bar_open << ',' + << bar->bar_high << ',' + << bar->bar_low << ',' + << bar->bar_close << ',' + << bar->volume << ',' + << bar->oi << std::endl ; + } + + if( csv_file_out.is_open() ) + csv_file_out.close(); +} + diff --git a/AmibrokerFeeder/RTDMan/source/worker.cpp b/AmibrokerFeeder/RTDMan/source/worker.cpp index f8ea2fa..417a4a7 100644 --- a/AmibrokerFeeder/RTDMan/source/worker.cpp +++ b/AmibrokerFeeder/RTDMan/source/worker.cpp @@ -57,7 +57,8 @@ Worker::Worker(): } LARGE_INTEGER start_now = {0}; // Start Timers immediately - SetWaitableTimer( AB_timer , &start_now, settings.bar_period, NULL, NULL, false ); +// SetWaitableTimer( AB_timer , &start_now, settings.bar_period, NULL, NULL, false ); + SetWaitableTimer( AB_timer , &start_now, settings.refresh_period, NULL, NULL, false ); // Bar period changed by Josh1 InitializeCriticalSection( &lock ); } @@ -94,19 +95,35 @@ void Worker::stop(){ } Worker::ScripState::ScripState() : - ltp(0), vol_today(0), oi(0), bar_high(0), bar_low(std::numeric_limits::infinity()), bar_open(0) + ltp(0), vol_today(0), oi(0), bar_high(0), bar_low(std::numeric_limits::infinity()), bar_open(0), + push(0), // Push flag added by Josh1 + ask_rate(0), ask_qty(0), bid_rate(0), bid_qty(0) //added by Boarders {} void Worker::ScripState::reset(){ ltp = 0; vol_today = 0; oi =0; bar_high = 0; bar_low = std::numeric_limits::infinity(); bar_open = 0; ltt=""; last_bar_ltt=""; + push = 0; // Push flag added by Josh1 + ask_rate =0; ask_qty =0; bid_rate =0; bid_qty =0; // added by Boarders } bool Worker::ScripState::operator==(const ScripState& right) const{ return (ltp == right.ltp) && (vol_today == right.vol_today) && (oi == right.oi ) && (bar_high == right.bar_high) && - (ltt == right.ltt) && (bar_low == right.bar_low ); + (ltt == right.ltt) && (bar_low == right.bar_low ) && + //Inserted by Boarders + (bid_rate == right.bid_rate ) && (ask_rate == right.ask_rate ) && + (ask_qty == right.ask_qty ) && (bid_qty == right.bid_qty ); } +//Inserted by Josh1 -------------------------------------------------------------------- +Worker::RTData::RTData() : + ltp(0), vol_today(0), oi(0),volume(0), ltt(""),ask_rate(0), ask_qty(0), bid_rate(0), bid_qty(0) +{} + +void Worker::RTData::reset(){ + ltp = 0; vol_today = 0; oi =0; volume= 0; ltt.clear(); ask_rate =0; ask_qty =0; bid_rate =0; bid_qty =0; +} +//end Inserted by Josh1 -------------------------------------------------------------------- /** * Connect Topics @@ -129,6 +146,11 @@ void Worker::connect(){ rtd_client->connectTopic(topic_id+LTT, topic_1, settings.scrips_array[i].topic_LTT ); rtd_client->connectTopic(topic_id+VOLUME_TODAY, topic_1, settings.scrips_array[i].topic_vol_today ); rtd_client->connectTopic(topic_id+OI, topic_1, settings.scrips_array[i].topic_OI ); + //Inserted by Boarders + rtd_client->connectTopic(topic_id+BID_RATE, topic_1, settings.scrips_array[i].topic_Bid_Rate ); + rtd_client->connectTopic(topic_id+ASK_RATE, topic_1, settings.scrips_array[i].topic_Ask_Rate ); + rtd_client->connectTopic(topic_id+BID_QTY, topic_1, settings.scrips_array[i].topic_Bid_Qty ); + rtd_client->connectTopic(topic_id+ASK_QTY, topic_1, settings.scrips_array[i].topic_Ask_Qty ); } } @@ -156,9 +178,14 @@ void Worker::poll(){ **/ void Worker::processRTDData( const std::map* data ){ - notifyActive(); - - for( auto i=data->begin(), end=data->end() ; i!=end ; ++i ){ + //inserted by Josh1 ------------------------------------------------------------ + RTData newdata; + int prev_field = 999999999; + int notified = 0; + cur_tm = Util::getTime("%H"); // + //end inserted by Josh1 ------------------------------------------------------------ + + for( auto i=data->begin(), end=data->end() ; i!=end ; ++i ){ const long topic_id = i->first; CComVariant topic_value = i->second; @@ -167,6 +194,7 @@ void Worker::processRTDData( const std::map* data ){ int script_id = ids.first; // Resolve Topic id to Scrip id and field int field_id = ids.second; +/********* Following code replaced by Josh1 with his code for two arrays current and previous ************************************************ EnterCriticalSection( &lock ); // Lock when accessing current[] / previous[] switch( field_id ){ @@ -194,6 +222,218 @@ void Worker::processRTDData( const std::map* data ){ } LeaveCriticalSection( &lock ) ; +/********* End code replaced by Josh1 with his code for two arrays current and previous ************************************************/ +// Changes made by Josh1 **************************************************************************** + ScripState *_current = & current[script_id]; + ScripState *_previous = & previous[script_id]; + + switch( field_id ){ + case VOLUME_TODAY :{ + long long vol_today = Util::getLong ( topic_value ); + newdata.vol_today = vol_today; + break ; + } + case LTT : { + newdata.ltt = Util::getString( topic_value ); + break ; + } + + case OI : newdata.oi = Util::getLong ( topic_value ); break ; + case BID_RATE : newdata.bid_rate = Util::getDouble ( topic_value ); break ; + case BID_QTY : newdata.bid_qty = Util::getLong ( topic_value ); break ; + case ASK_RATE : newdata.ask_rate = Util::getDouble ( topic_value ); break ; + case ASK_QTY : newdata.ask_qty = Util::getLong ( topic_value ); break ; + + case LTP :{ // This is last field received from RTD Server (Enum = 3) + std::string str ; + str = Util::getString( topic_value ); + if (str.length() < 1) { //empty LTP sent by server in the morning in some cases + newdata.reset(); //crashes RTDMan.... so skip + continue; + } + else { + newdata.ltp = Util::getDouble( topic_value ); + } + + std::string bar_ltt = newdata.ltt.substr(0,2); //get time hour from newdata.ltt + if(cur_tm == "09" && bar_ltt == "15"){ // Compare with current hour. If yesterdays's tick in the morning, + newdata.reset(); //skip + continue; + } + + newdata.ltp = newdata.ltp * settings.scrips_array[script_id].ltp_multiplier ; + + if(newdata.ltt.length() < 5 ) newdata.ltt = Util::getTime("%H:%M:%S"); //This is for Index which have no LTT field; + +/********************************************************************************************************** + if( !isMarketTime( newdata.ltt )){ + newdata.reset(); //skip quotes outside market hours + continue; + } +/********************************************************************************************************/ +/************************* Append milliseconds to LTT ------- Inserted by Josh1 **************************/ + if(settings.bar_period == 0) { + SYSTEMTIME lt; + GetLocalTime(<); + std::stringstream stream; + stream <vol_today << ","; + std::cout << "OI- " <vol_today){ + newdata.reset(); //If there is no change in volume means no trade so Skip ! + continue; + } + } + break ; + } + } +/**********************************************************************************************************/ + if (settings.view_tic_data == 1){ + std::cout <<"\n"<< script_id << " - "; + std::cout << settings.scrips_array[script_id].topic_name << ", "; + std::cout << "LTT - " << newdata.ltt << ", "; + std::cout << "LTP - " << newdata.ltp << ", "; + std::cout << "Vol_today - " << newdata.vol_today << ", "; + std::cout << "OI - " <push == 1) { + *_previous = *_current; + } + else{ + previous[script_id].ltt = current[script_id].ltt; + previous[script_id].vol_today = _current->vol_today; + } + if (settings.use_ltq != 1){ + if( newdata.vol_today !=0 && previous[script_id].vol_today == 0){ + if(newdata.ltt.substr(0,3) != "0915" || (newdata.ltt.substr(0,3) != "1000" + && settings.scrips_array[script_id].topic_name.substr(0,3)=="mcx")){ //// Except for start of day + previous[script_id].vol_today = newdata.vol_today; // On startup prev vol is 0, + _current->vol_today = newdata.vol_today; + } //Set it so that we can get first bar volume + } + } + _current->bar_high = _current->bar_low = _current->bar_open = _current->ltp = newdata.ltp; + _current->ltt = newdata.ltt; + _current->oi = newdata.oi; + if(settings.use_ltq == 1) { + _current->volume = newdata.vol_today ; + } + else { + if(settings.bar_period == 0){ + _current->volume = newdata.vol_today - _current->vol_today; + } + else{ + _current->volume = newdata.vol_today- previous[script_id].vol_today; //Changed by Josh1 + } + } + _current->vol_today = newdata.vol_today; + _current->bid_rate = newdata.bid_rate ; + _current->ask_rate = newdata.ask_rate; + _current->bid_qty = newdata.bid_qty ; + _current->ask_qty = newdata.ask_qty ; + + _current->push = 1; + newdata.reset(); + } + else { + _current->ltp = newdata.ltp; + _current->oi = newdata.oi; + if( _current->bar_high < _current->ltp ) _current->bar_high = _current->ltp; + if( _current->bar_low > _current->ltp ) _current->bar_low = _current->ltp; + if(settings.use_ltq == 1) { + _current->volume = _current->volume + newdata.vol_today; + } + else { + if(settings.bar_period == 0){ //Inserted 11-4-16 + _current->volume = newdata.vol_today - _current->vol_today; + } + else{ + _current->volume = newdata.vol_today - previous[script_id].vol_today; + } + } + _current->vol_today = newdata.vol_today; + _current->bid_rate = newdata.bid_rate ; + _current->ask_rate = newdata.ask_rate; + _current->bid_qty = newdata.bid_qty ; + _current->ask_qty = newdata.ask_qty ; + _current->push = 1; + newdata.reset(); + } +/**********************************************************************************************************/ + if (settings.view_bar_data == 1){ + std::cout <<"\n"<< script_id << " - "; + std::cout << settings.scrips_array[script_id].ticker << " "; + std::cout << "LTT- " << _current->ltt << ", "; + std::cout << "LTP- " << _current->ltp << ", "; + std::cout << "Vol- " << _current->volume << ", "; + std::cout << "OI- " << _current->oi << ", "; + std::cout << "B - " << _current->bid_rate << ", "; + std::cout << "A - " << _current->ask_rate << ", "; + std::cout << "Bq - " << _current->bid_qty << ", "; + std::cout << "Aq - " << _current->ask_qty << ", "; + } +/**********************************************************************************************************/ + + LeaveCriticalSection( &lock ) ; + + } + prev_field = field_id; //Set previous field id + +//****** End Changes made by Josh1 ********************************************************************** } } @@ -208,6 +448,8 @@ void Worker::threadEntryDummy(void* _this){ void Worker::amibrokerPoller(){ std::vector new_bars; + std::stringstream current_prices; + if( settings.isTargetNT()){ ninja_trader = new NinjaTrader(); @@ -238,6 +480,7 @@ void Worker::amibrokerPoller(){ throw( msg.str() ); } +/********* Following code replaced by Josh1 with his code for two arrays current and previous ************************************************ // Shared data access start EnterCriticalSection( &lock ); @@ -310,6 +553,203 @@ void Worker::amibrokerPoller(){ writeArchiveCsv( new_bars ); // Archive ticks to be used for backfill } new_bars.clear(); +/********* End code replaced by Josh1 with his code for two arrays current and previous ************************************************/ +// Changes made by Josh1 **************************************************************************** + + csv_file_out.open( settings.csv_path ); // Setup output stream to csv file + if( !csv_file_out.is_open() ){ // Reopening will also clear old content by default + throw( "Error opening file - " + settings.csv_path ); + } + + int records =0; + + for( int i=0 ; iltp << std::endl; + + if (_prev->push == 1) { + if( settings.isTargetNT()){ + if(settings.bar_period==0) { + timestamp4=today_date+_prev->ltt.substr(0,2)+_prev->ltt.substr(3,2)+_prev->ltt.substr(6,2); + } else {timestamp4=today_date+_prev->ltt.substr(6);} + ninja_trader->LastPlayback( Scripname, _prev->ltp, _prev->volume, timestamp4 ); + if (!(_prev->bid_rate == 0 && _prev->ask_rate == 0)){ + if (_prev->bid_qty == 0 && _prev->ask_qty == 0){ + if((_prev->ltp - _prev->bid_rate) < (_prev->ask_rate - _prev->ltp)){ + _prev->bid_qty = _prev->volume; + } + else { _prev->ask_qty = _prev->volume; + } + } + ninja_trader->AskPlayback( Scripname, _prev->ask_rate, _prev->ask_qty, timestamp4); //bar->ask_qty, timestamp4 ); + ninja_trader->BidPlayback( Scripname, _prev->bid_rate, _prev->bid_qty, timestamp4 ); //bar->bid_qty, timestamp4) + + if(settings.view_NT_data == 1) { + std::cout << Scripname << ',' // $FORMAT Ticker, Date_YMD, Time, Open, High, + << timestamp4 << ',' // Low, Close, Volume, OpenInt + << _prev->ltp << ',' // ltp is close + << _prev->volume << ',' + << _prev->bid_rate << ',' // Say Aux1 + << _prev->ask_rate + << _prev->bid_qty << ',' //bid_qty goes to Volume + << _prev->ask_qty << ',' //ask_qty goes to Oi + << std::endl ; + } + } + } + + else{ + quotation << Scripname << ',' // $FORMAT Ticker, Date_YMD, Time, Open, High, + << today_date << ',' // Low, Close, Volume, OpenInt + << _prev->ltt << ',' + << _prev->bar_open << ',' + << _prev->bar_high << ',' + << _prev->bar_low << ',' + << _prev->ltp << ',' // ltp is close + << _prev->volume << ',' + << _prev->oi ; + if (!(_prev->bid_rate == 0 && _prev->ask_rate == 0)){ + quotation << ',' + << _prev->bid_rate << ',' // Say Aux1 + << _prev->ask_rate + << std::endl ; + + if(!(_prev->bid_qty == 0 && _prev->ask_qty == 0)){ + quotation << Scripname+"e" << ',' // $FORMAT Ticker, Date_YMD, Time, Open, High, + << today_date << ',' // Low, Close, Volume, OpenInt + << _prev->ltt << ',' + << ',' //open << + << _prev->ask_rate << ',' //high << + << _prev->bid_rate << ',' //Low << + << _prev->ltp << ',' //Close << + << _prev->bid_qty << ',' //bid_qty goes to Volume + << _prev->ask_qty << ',' //ask_qty goes to Oi + << std::endl ; //<< Aux1 and Aux2 empty + } + } + else{quotation << std::endl ;} + quotation2 = quotation.str(); + csv_file_out << quotation.rdbuf(); + if(settings.is_archive) { + scrip_file_out.open( settings.csv_folder_path + Scripname + ".csv", std::fstream::out | std::fstream::app ); + + if( !scrip_file_out.is_open() ){ + throw( "Error opening file - " + settings.csv_folder_path + Scripname + ".csv" ); + } + scrip_file_out << quotation2 ; + if( scrip_file_out.is_open() ){ + scrip_file_out.close(); + } + } + } + _prev->push = 0; + quotation.clear(); + records++; + } + + if (_current->push == 1) { + if( settings.isTargetNT()){ + if(settings.bar_period == 0) { + timestamp4=today_date+_current->ltt.substr(0,2)+_current->ltt.substr(3,2)+_current->ltt.substr(6,2); + } else { + timestamp4=today_date+_current->ltt.substr(6);} + + ninja_trader->LastPlayback( Scripname, _current->ltp, _current->volume, timestamp4 ); + if (!(_current->bid_rate == 0 && _current->ask_rate == 0)){ + if (_current->bid_qty == 0 && _current->ask_qty == 0){ + if((_current->ltp - _current->bid_rate) < (_current->ask_rate - _current->ltp)){ + _current->bid_qty = _current->volume; + } + else { _current->ask_qty = _current->volume; + } + } + ninja_trader->AskPlayback( Scripname, _current->ask_rate, _current->ask_qty, timestamp4); //bar->ask_qty, timestamp4 ); + ninja_trader->BidPlayback( Scripname, _current->bid_rate, _current->bid_qty, timestamp4 ); //bar->bid_qty, timestamp4); + if(settings.view_NT_data == 1) { + std::cout << Scripname << ',' // $FORMAT Ticker, Date_YMD, Time, Open, High, + << timestamp4 << ',' // Low, Close, Volume, OpenInt + << _current->ltp << ',' // ltp is close + << _current->volume << ',' + << _current->bid_rate << ',' // bid_rate goes to Say Aux1 + << _current->ask_rate << ',' // ask_rate goes to say Aux2 + << _current->bid_qty << ',' // bid_qty goes to Volume + << _current->ask_qty << ',' // ask_qty goes to OI + << std::endl ; + } + } + } + else{ + quotation << Scripname << ',' // $FORMAT Ticker, Date_YMD, Time, Open, High, + << today_date << ',' // Low, Close, Volume, OpenInt + << _current->ltt << ',' + << _current->bar_open << ',' // O + << _current->bar_high << ',' // H + << _current->bar_low << ',' // L + << _current->ltp << ',' // ltp is close + << _current->volume << ',' + << _current->oi ; + if (!(_current->bid_rate == 0 && _current->ask_rate == 0)){ + quotation << ',' + << _current->bid_rate << ',' // bid_rate goes to Say Aux1 + << _current->ask_rate // ask_rate goes to say Aux2 + << std::endl ; + + if(!(_current->bid_qty == 0 && _current->ask_qty == 0)){ + quotation << Scripname+"e" << ',' // $FORMAT Ticker, Date_YMD, Time, Open, High, + << today_date << ',' // Low, Close, Volume, OpenInt + << _current->ltt << ',' + << ',' // O + << _current->ask_rate << ',' // H + << _current->bid_rate << ',' // L + << _current->ltp << ',' // C + << _current->bid_qty << ',' // bid_qty goes to Volume + << _current->ask_qty << ',' // ask_qty goes to OI + << std::endl ; //<< Aux1 and Aux2 empty + } + } + else{quotation << std::endl ;} + quotation2 = quotation.str(); + csv_file_out << quotation.rdbuf(); + if(settings.is_archive) { + scrip_file_out.open( settings.csv_folder_path + Scripname + ".csv", std::fstream::out | std::fstream::app ); + + if( !scrip_file_out.is_open() ){ + throw( "Error opening file - " + settings.csv_folder_path + Scripname + ".csv" ); + } + scrip_file_out << quotation2; + if( scrip_file_out.is_open() ) + scrip_file_out.close(); + } + } + _current->push = 0; + records++; + quotation.clear(); + } + + LeaveCriticalSection( &lock ); // Shared data access end + + } + + csv_file_out.close(); + writeCurrentPrices(current_prices); // Output latest prices for each scrip + if(records == 0){ + notifyInactive(); + } + if( !settings.isTargetNT()){ + amibroker->import(); + if(settings.request_refresh == 1){ // AmiBroker version 5.3 and below do not refresh automatically after import + amibroker->refreshAll(); + } + } + } } @@ -350,6 +790,9 @@ bool Worker::isMarketTime ( const std::string &time ){ // return time >= settings.open_time && time <= settings.close_time ; // So string compare works } + +/***************************** Removed by Josh1 *********************************************************** + void Worker::writeABCsv( const std::vector & bars ){ csv_file_out.open( settings.csv_path ); // Setup output stream to csv file @@ -377,10 +820,9 @@ void Worker::writeABCsv( const std::vector & bars ){ csv_file_out.close(); } -/* Send OHLC to NinjaTrader Workaround - Send OHLC as ticks with 1/4 volume -*/ + void Worker::pushToNT( const std::vector & bars ){ int volume = 0 ; @@ -435,4 +877,20 @@ void Worker::writeArchiveCsv( const std::vector & bars ){ if( csv_file_out.is_open() ) csv_file_out.close(); } +/********************** end removed by Josh1 *******************************************/ + +void Worker::writeCurrentPrices( const std::stringstream & current_prices){ + + if( csv_file_out.is_open() ) + csv_file_out.close(); + csv_file_out.open( settings.csv_folder_path + "last_prices.csv", std::fstream::out ); + if( !csv_file_out.is_open() ){ + throw( "Error opening file - last_prices.csv" ); + } + + csv_file_out << current_prices.rdbuf() << std::flush; + + if( csv_file_out.is_open() ) + csv_file_out.close(); +}