Fix
This commit is contained in:
@@ -82,7 +82,7 @@ class Strategy(PulseWire[plugin.StrategyEngineMessage, plugin.StrategyEngineMess
|
|||||||
def getWatchList(self):
|
def getWatchList(self):
|
||||||
self.send(plugin.StrategyMessage.GetWatchList())
|
self.send(plugin.StrategyMessage.GetWatchList())
|
||||||
|
|
||||||
def getCandleStick(self, symbol: str, interval: general.CandleInterval, count: general.u32):
|
def getCandleStick(self, symbol: str, interval: general.CandleIntervalType, count: general.u32):
|
||||||
msg = plugin.StrategyMessage.RequestCandlestick()
|
msg = plugin.StrategyMessage.RequestCandlestick()
|
||||||
msg.symbol = symbol
|
msg.symbol = symbol
|
||||||
msg.interval = interval
|
msg.interval = interval
|
||||||
|
|||||||
@@ -76,30 +76,59 @@ class f32(PulseUnit): pass
|
|||||||
class f64(PulseUnit): pass
|
class f64(PulseUnit): pass
|
||||||
|
|
||||||
class decimal(PulseUnit):
|
class decimal(PulseUnit):
|
||||||
size = struct.calcsize("<qb")
|
# Exactly 16 bytes to match Rust's [u8; 16] output
|
||||||
|
size = 16
|
||||||
|
|
||||||
def __init__(self, value):
|
def __init__(self, value):
|
||||||
self.value = Decimal(value)
|
self.value = Decimal(value)
|
||||||
|
|
||||||
def to_com(self):
|
def to_com(self) -> bytes:
|
||||||
sign, digits, exponent = self.value.as_tuple()
|
sign, digits, exponent = self.value.as_tuple()
|
||||||
|
|
||||||
if not isinstance(exponent, int):
|
if not isinstance(exponent, int):
|
||||||
raise ValueError("Cannot serialize NaN or Infinity")
|
raise ValueError("Cannot serialize NaN or Infinity")
|
||||||
|
|
||||||
scale = -exponent
|
scale = -exponent
|
||||||
integer = int("".join(map(str, digits)))
|
mantissa = int("".join(map(str, digits)))
|
||||||
|
|
||||||
|
# Handle positive exponents (e.g. 5E+2 -> scale 0, mantissa 500)
|
||||||
|
if scale < 0:
|
||||||
|
mantissa = mantissa * (10 ** -scale)
|
||||||
|
scale = 0
|
||||||
|
|
||||||
|
# Max scale allowed in rust_decimal is 28
|
||||||
|
if scale > 28:
|
||||||
|
raise ValueError(f"Scale {scale} exceeds maximum allowed (28)")
|
||||||
|
|
||||||
|
# Split 96-bit mantissa into three 32-bit chunks
|
||||||
|
lo = mantissa & 0xFFFFFFFF
|
||||||
|
mid = (mantissa >> 32) & 0xFFFFFFFF
|
||||||
|
hi = (mantissa >> 64) & 0xFFFFFFFF
|
||||||
|
|
||||||
|
# Construct flags: scale is in bits 16-23, sign is bit 31
|
||||||
|
flags = (scale << 16) & 0x00FF0000
|
||||||
if sign:
|
if sign:
|
||||||
integer = -integer
|
flags |= 0x80000000
|
||||||
|
|
||||||
|
return struct.pack("<4I", flags, lo, mid, hi)
|
||||||
return struct.pack("<qb", integer, scale)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_com(cls, data: bytes, offset: int = 0) -> tuple[typing.Any, int]:
|
def from_com(cls, data: bytes, offset: int = 0) -> tuple[typing.Any, int]:
|
||||||
integer, scale = struct.unpack_from("<qb", data, offset)
|
# Unpack four 32-bit unsigned integers (Little-Endian)
|
||||||
|
flags, lo, mid, hi = struct.unpack_from("<4I", data, offset)
|
||||||
|
|
||||||
value = Decimal(integer) / (Decimal(10) ** scale)
|
# Extract scale (Bits 16-23)
|
||||||
|
scale = (flags >> 16) & 0xFF
|
||||||
|
|
||||||
|
# Extract sign (Bit 31)
|
||||||
|
is_negative = (flags & 0x80000000) != 0
|
||||||
|
|
||||||
|
# Reconstruct the 96-bit integer mantissa
|
||||||
|
mantissa = lo | (mid << 32) | (hi << 64)
|
||||||
|
|
||||||
|
# Convert to Python Decimal
|
||||||
|
value = Decimal(mantissa) / (Decimal(10) ** scale)
|
||||||
|
if is_negative:
|
||||||
|
value = -value
|
||||||
|
|
||||||
return cls(value), offset + cls.size
|
return cls(value), offset + cls.size
|
||||||
+14
-14
@@ -19,20 +19,20 @@ class LogKind(PulseWire):
|
|||||||
|
|
||||||
@pwp_enum
|
@pwp_enum
|
||||||
class CandleInterval(PulseWire):
|
class CandleInterval(PulseWire):
|
||||||
class OneMinute: pass
|
class OneMinute(PulseWire): pass
|
||||||
class ThreeMinutes: pass
|
class ThreeMinutes(PulseWire): pass
|
||||||
class FiveMinutes: pass
|
class FiveMinutes(PulseWire): pass
|
||||||
class FifteenMinutes: pass
|
class FifteenMinutes(PulseWire): pass
|
||||||
class ThirtyMinutes: pass
|
class ThirtyMinutes(PulseWire): pass
|
||||||
class OneHour: pass
|
class OneHour(PulseWire): pass
|
||||||
class TwoHours: pass
|
class TwoHours(PulseWire): pass
|
||||||
class FourHours: pass
|
class FourHours(PulseWire): pass
|
||||||
class EightHours: pass
|
class EightHours(PulseWire): pass
|
||||||
class TwelveHours: pass
|
class TwelveHours(PulseWire): pass
|
||||||
class OneDay: pass
|
class OneDay(PulseWire): pass
|
||||||
class ThreeDays: pass
|
class ThreeDays(PulseWire): pass
|
||||||
class OneWeek: pass
|
class OneWeek(PulseWire): pass
|
||||||
class OneMonth: pass
|
class OneMonth(PulseWire): pass
|
||||||
|
|
||||||
@pwp
|
@pwp
|
||||||
class Signal(PulseWire):
|
class Signal(PulseWire):
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class StrategyMessage(PulseWire):
|
|||||||
|
|
||||||
class RequestCandlestick(PulseWire):
|
class RequestCandlestick(PulseWire):
|
||||||
symbol: str
|
symbol: str
|
||||||
interval: general.CandleInterval
|
interval: general.CandleIntervalType
|
||||||
count: u32
|
count: u32
|
||||||
|
|
||||||
class Subscribe(PulseWire):
|
class Subscribe(PulseWire):
|
||||||
|
|||||||
Reference in New Issue
Block a user