#ifndef INTRADAY_RECORD_H
#define INTRADAY_RECORD_H
const float SINGLE_TRADE_WITH_BID_ASK = 0.0F;
const float FIRST_SUB_TRADE_OF_UNBUNDLED_TRADE_VALUE = -1.99900095e+37F;
const float LAST_SUB_TRADE_OF_UNBUNDLED_TRADE_VALUE = -1.99900197e+37F;
struct s_IntradayRecord
{
SCDateTimeMS DateTime;
float Open;
float High;
float Low;
float Close;
uint32_t NumTrades;
uint32_t TotalVolume;
uint32_t BidVolume;
uint32_t AskVolume;
s_IntradayRecord();
s_IntradayRecord(int Value);
bool operator == (const s_IntradayRecord& Record) const;
s_IntradayRecord& operator = (const s_IntradayRecord& Record);
s_IntradayRecord& operator += (const float Amount);
s_IntradayRecord& operator *= (const float Multiplier);
s_IntradayRecord& operator /= (const float Divisor);
void AddAdjustment
( const float Amount
, const bool AdjustZeroValues
);
bool IsEmpty() const;
void Clear();
void ClearOpenFlags();
void Fix();
bool IsSingleTradeWithBidAsk() const;
bool IsFirstSubTradeOfUnbundledTrade() const;
bool IsLastSubTradeOfUnbundledTrade() const;
bool IsFirstOrLastSubTradeOfUnbundledTrade() const;
bool IsBidAskUpdateOnly() const;
float GetOpen() const;
float GetHigh() const;
float GetLow() const;
float GetClose() const;
float GetBidPrice() const;
float GetAskPrice() const;
};
struct s_IntradayFileHeader
{
static const uint32_t UNIQUE_HEADER_ID = 0x44494353;
uint32_t FileTypeUniqueHeaderID;
uint32_t HeaderSize;
uint32_t RecordSize;
uint16_t Version;
uint16_t Unused1;
uint32_t Unused2;
char Reserve[36];
s_IntradayFileHeader()
: FileTypeUniqueHeaderID(UNIQUE_HEADER_ID)
, HeaderSize(sizeof(s_IntradayFileHeader))
, RecordSize(sizeof(s_IntradayRecord))
, Version(1)
, Unused1(0)
, Unused2(0)
{
memset(Reserve, 0, sizeof(Reserve));
}
};
inline s_IntradayRecord::s_IntradayRecord()
{
Clear();
}
inline s_IntradayRecord::s_IntradayRecord(int Value)
{
Clear();
}
inline bool s_IntradayRecord::operator ==
(const s_IntradayRecord& Record
) const
{
return memcmp(this, &Record, sizeof(s_IntradayRecord)) == 0;
}
inline s_IntradayRecord&
s_IntradayRecord::operator =
(const s_IntradayRecord& Record
)
{
if (&Record == this)
return *this;
memcpy(this, &Record, sizeof(s_IntradayRecord));
return *this;
}
inline s_IntradayRecord&
s_IntradayRecord::operator += (const float Amount)
{
if (!IsSingleTradeWithBidAsk())
Open += Amount;
High += Amount;
Low += Amount;
Close += Amount;
return *this;
}
inline s_IntradayRecord&
s_IntradayRecord::operator *= (const float Multiplier)
{
if (!IsSingleTradeWithBidAsk())
Open *= Multiplier;
High *= Multiplier;
Low *= Multiplier;
Close *= Multiplier;
return *this;
}
inline s_IntradayRecord&
s_IntradayRecord::operator /= (const float Divisor)
{
if (!IsSingleTradeWithBidAsk())
Open /= Divisor;
High /= Divisor;
Low /= Divisor;
Close /= Divisor;
return *this;
}
inline void s_IntradayRecord::AddAdjustment
(const float Amount
, const bool AdjustZeroValues
)
{
if (!IsSingleTradeWithBidAsk())
{
if (Open != 0.0f || AdjustZeroValues)
Open += Amount;
}
if (High != 0.0f || AdjustZeroValues)
High += Amount;
if (Low != 0.0f || AdjustZeroValues)
Low += Amount;
if (Close != 0.0f || AdjustZeroValues)
Close += Amount;
}
inline bool s_IntradayRecord::IsEmpty() const
{
return DateTime.IsUnset()
&& Open == 0.0f
&& High == 0.0f
&& Low == 0.0f
&& Close == 0.0f
&& NumTrades == 0
&& TotalVolume == 0;
}
inline void s_IntradayRecord::Clear()
{
DateTime.Clear();
Open = 0.0f;
High = 0.0f;
Low = 0.0f;
Close = 0.0f;
NumTrades = 0;
TotalVolume = 0;
BidVolume = 0;
AskVolume = 0;
}
inline void s_IntradayRecord::ClearOpenFlags()
{
Open = 0.0f;
}
inline void s_IntradayRecord::Fix()
{
if (NumTrades > INT_MAX)
NumTrades = 0;
if (TotalVolume > INT_MAX)
TotalVolume = 0;
if (BidVolume > INT_MAX)
BidVolume = 0;
if (AskVolume > INT_MAX)
AskVolume = 0;
}
inline bool s_IntradayRecord::IsSingleTradeWithBidAsk() const
{
return NumTrades == 1
&& (Open == 0.0
|| Open == FIRST_SUB_TRADE_OF_UNBUNDLED_TRADE_VALUE
|| Open == LAST_SUB_TRADE_OF_UNBUNDLED_TRADE_VALUE
);
}
inline bool s_IntradayRecord::IsFirstSubTradeOfUnbundledTrade() const
{
return (Open == FIRST_SUB_TRADE_OF_UNBUNDLED_TRADE_VALUE);
}
inline bool s_IntradayRecord::IsLastSubTradeOfUnbundledTrade() const
{
return (Open == LAST_SUB_TRADE_OF_UNBUNDLED_TRADE_VALUE);
}
inline bool s_IntradayRecord::IsFirstOrLastSubTradeOfUnbundledTrade() const
{
return Open == FIRST_SUB_TRADE_OF_UNBUNDLED_TRADE_VALUE
|| Open == LAST_SUB_TRADE_OF_UNBUNDLED_TRADE_VALUE;
}
inline bool s_IntradayRecord::IsBidAskUpdateOnly() const
{
return NumTrades == 1
&& TotalVolume == 0
&& Open == 0.0
&& High != 0.0
&& Low != 0.0;
}
inline float s_IntradayRecord::GetOpen() const
{
if (IsSingleTradeWithBidAsk())
return Close;
return Open;
}
inline float s_IntradayRecord::GetHigh() const
{
if (IsSingleTradeWithBidAsk())
return Close;
return High;
}
inline float s_IntradayRecord::GetLow() const
{
if (IsSingleTradeWithBidAsk())
return Close;
return Low;
}
inline float s_IntradayRecord::GetClose() const
{
return Close;
}
inline float s_IntradayRecord::GetBidPrice() const
{
if (!IsSingleTradeWithBidAsk())
return 0.0f;
return Low;
}
inline float s_IntradayRecord::GetAskPrice() const
{
if (!IsSingleTradeWithBidAsk())
return 0.0f;
return High;
}
#endif