286 lines
9.9 KiB
C#
286 lines
9.9 KiB
C#
using System;
|
|
using System.Collections.Generic; // Required for List<T>
|
|
using System.IO; // For File operations
|
|
using System.Runtime.InteropServices; // Required for StructLayout and Marshal
|
|
|
|
namespace Zorro
|
|
{
|
|
/// <summary>
|
|
/// Provides generic methods for loading and saving arrays of structures
|
|
/// from/to binary files using marshalling.
|
|
/// This class is intended for internal use within this assembly.
|
|
/// </summary>
|
|
internal static class BinaryFileHandler
|
|
{
|
|
public static void SaveArrayAsBlock<T>(string filePath, T[] data) where T : struct
|
|
{
|
|
if (data == null || data.Length == 0)
|
|
{
|
|
File.WriteAllBytes(filePath, Array.Empty<byte>());
|
|
return;
|
|
}
|
|
|
|
int structSize = Marshal.SizeOf(typeof(T));
|
|
byte[] byteArray = new byte[data.Length * structSize];
|
|
IntPtr buffer = Marshal.AllocHGlobal(structSize);
|
|
try
|
|
{
|
|
for (int i = 0; i < data.Length; i++)
|
|
{
|
|
Marshal.StructureToPtr(data[i], buffer, false);
|
|
Marshal.Copy(buffer, byteArray, i * structSize, structSize);
|
|
}
|
|
File.WriteAllBytes(filePath, byteArray);
|
|
}
|
|
finally
|
|
{
|
|
Marshal.FreeHGlobal(buffer);
|
|
}
|
|
}
|
|
|
|
public static T[]? LoadArrayAsBlock<T>(string filePath) where T : struct
|
|
{
|
|
if (!File.Exists(filePath))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
byte[] byteArray = File.ReadAllBytes(filePath);
|
|
if (byteArray.Length == 0)
|
|
{
|
|
return Array.Empty<T>();
|
|
}
|
|
|
|
int structSize = Marshal.SizeOf(typeof(T));
|
|
|
|
if (byteArray.Length % structSize != 0)
|
|
{
|
|
throw new ArgumentException($"File size ({byteArray.Length} bytes) is not a valid multiple of the structure size ({structSize} bytes) for type {typeof(T).Name}. The file may be corrupted or not in the expected format.");
|
|
}
|
|
|
|
int itemCount = byteArray.Length / structSize;
|
|
T[] dataArray = new T[itemCount];
|
|
IntPtr buffer = Marshal.AllocHGlobal(structSize);
|
|
try
|
|
{
|
|
for (int i = 0; i < itemCount; i++)
|
|
{
|
|
Marshal.Copy(byteArray, i * structSize, buffer, structSize);
|
|
dataArray[i] = Marshal.PtrToStructure<T>(buffer);
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
Marshal.FreeHGlobal(buffer);
|
|
}
|
|
return dataArray;
|
|
}
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
|
|
public struct ZorroT1
|
|
{
|
|
public double OADate;
|
|
public float Value;
|
|
|
|
/// <summary>
|
|
/// Returns the time as a UTC DateTime object.
|
|
/// Note: DateTime.FromOADate returns a DateTime with Kind=Unspecified.
|
|
/// We specify it as UTC as Zorro DATEs are GMT/UTC.
|
|
/// </summary>
|
|
public DateTime TimeUtc => DateTime.SpecifyKind(DateTime.FromOADate(OADate), DateTimeKind.Utc);
|
|
|
|
public ZorroT1(double oaDate, float value)
|
|
{
|
|
OADate = oaDate;
|
|
Value = value;
|
|
}
|
|
public ZorroT1(DateTime dateTime, float value)
|
|
{
|
|
// Ensure the DateTime is converted to its UTC equivalent for OADate
|
|
OADate = dateTime.ToUniversalTime().ToOADate();
|
|
Value = value;
|
|
}
|
|
|
|
public static void SaveToFile(string filePath, ZorroT1[] data) => BinaryFileHandler.SaveArrayAsBlock<ZorroT1>(filePath, data);
|
|
public static ZorroT1[]? LoadFromFile(string filePath) => BinaryFileHandler.LoadArrayAsBlock<ZorroT1>(filePath);
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
|
|
public struct ZorroT2
|
|
{
|
|
public double OADate;
|
|
public float Price;
|
|
public float Volume;
|
|
|
|
public DateTime TimeUtc => DateTime.SpecifyKind(DateTime.FromOADate(OADate), DateTimeKind.Utc);
|
|
|
|
public ZorroT2(double oaDate, float price, float volume)
|
|
{
|
|
OADate = oaDate;
|
|
Price = price;
|
|
Volume = volume;
|
|
}
|
|
public ZorroT2(DateTime dateTime, float price, float volume)
|
|
{
|
|
OADate = dateTime.ToUniversalTime().ToOADate();
|
|
Price = price;
|
|
Volume = volume;
|
|
}
|
|
|
|
public static void SaveToFile(string filePath, ZorroT2[] data) => BinaryFileHandler.SaveArrayAsBlock<ZorroT2>(filePath, data);
|
|
public static ZorroT2[]? LoadFromFile(string filePath) => BinaryFileHandler.LoadArrayAsBlock<ZorroT2>(filePath);
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
|
|
public struct ZorroT6
|
|
{
|
|
public double OADate;
|
|
public float High;
|
|
public float Low;
|
|
public float Open;
|
|
public float Close;
|
|
public float AdditionalValue1;
|
|
public float AdditionalValue2;
|
|
|
|
public DateTime TimeUtc => DateTime.SpecifyKind(DateTime.FromOADate(OADate), DateTimeKind.Utc);
|
|
|
|
public ZorroT6(double oaDate, float high, float low, float open, float close, float additionalValue1, float additionalValue2)
|
|
{
|
|
OADate = oaDate;
|
|
High = high;
|
|
Low = low;
|
|
Open = open;
|
|
Close = close;
|
|
AdditionalValue1 = additionalValue1;
|
|
AdditionalValue2 = additionalValue2;
|
|
}
|
|
public ZorroT6(DateTime dateTime, float high, float low, float open, float close, float additionalValue1, float additionalValue2)
|
|
{
|
|
OADate = dateTime.ToUniversalTime().ToOADate();
|
|
High = high;
|
|
Low = low;
|
|
Open = open;
|
|
Close = close;
|
|
AdditionalValue1 = additionalValue1;
|
|
AdditionalValue2 = additionalValue2;
|
|
}
|
|
|
|
public static void SaveToFile(string filePath, ZorroT6[] data) => BinaryFileHandler.SaveArrayAsBlock<ZorroT6>(filePath, data);
|
|
public static ZorroT6[]? LoadFromFile(string filePath) => BinaryFileHandler.LoadArrayAsBlock<ZorroT6>(filePath);
|
|
}
|
|
|
|
// --- Builder Classes for Incremental Array Construction ---
|
|
|
|
public class ZorroT1ArrayBuilder
|
|
{
|
|
private readonly List<ZorroT1> _items;
|
|
|
|
public ZorroT1ArrayBuilder(int initialCapacity = 0)
|
|
{
|
|
_items = initialCapacity > 0 ? new List<ZorroT1>(initialCapacity) : new List<ZorroT1>();
|
|
}
|
|
|
|
public ZorroT1ArrayBuilder Add(DateTime time, float value)
|
|
{
|
|
// Constructor of ZorroT1 now handles UTC conversion
|
|
_items.Add(new ZorroT1(time, value));
|
|
return this;
|
|
}
|
|
|
|
public ZorroT1ArrayBuilder Add(double oaDate, float value)
|
|
{
|
|
_items.Add(new ZorroT1(oaDate, value));
|
|
return this;
|
|
}
|
|
|
|
public ZorroT1ArrayBuilder Add(ZorroT1 item)
|
|
{
|
|
_items.Add(item);
|
|
return this;
|
|
}
|
|
|
|
public ZorroT1[] ToArray() => _items.ToArray();
|
|
public void Clear() => _items.Clear();
|
|
public int Count => _items.Count;
|
|
|
|
public void SaveToFile(string filePath)
|
|
{
|
|
ZorroT1.SaveToFile(filePath, _items.ToArray());
|
|
}
|
|
}
|
|
|
|
public class ZorroT2ArrayBuilder
|
|
{
|
|
private readonly List<ZorroT2> _items;
|
|
|
|
public ZorroT2ArrayBuilder(int initialCapacity = 0)
|
|
{
|
|
_items = initialCapacity > 0 ? new List<ZorroT2>(initialCapacity) : new List<ZorroT2>();
|
|
}
|
|
|
|
public ZorroT2ArrayBuilder Add(DateTime time, float price, float volume)
|
|
{
|
|
_items.Add(new ZorroT2(time, price, volume));
|
|
return this;
|
|
}
|
|
|
|
public ZorroT2ArrayBuilder Add(double oaDate, float price, float volume)
|
|
{
|
|
_items.Add(new ZorroT2(oaDate, price, volume));
|
|
return this;
|
|
}
|
|
|
|
public ZorroT2ArrayBuilder Add(ZorroT2 item)
|
|
{
|
|
_items.Add(item);
|
|
return this;
|
|
}
|
|
|
|
public ZorroT2[] ToArray() => _items.ToArray();
|
|
public void Clear() => _items.Clear();
|
|
public int Count => _items.Count;
|
|
|
|
public void SaveToFile(string filePath)
|
|
{
|
|
ZorroT2.SaveToFile(filePath, _items.ToArray());
|
|
}
|
|
}
|
|
|
|
public class ZorroT6ArrayBuilder
|
|
{
|
|
private readonly List<ZorroT6> _items;
|
|
|
|
public ZorroT6ArrayBuilder(int initialCapacity = 0)
|
|
{
|
|
_items = initialCapacity > 0 ? new List<ZorroT6>(initialCapacity) : new List<ZorroT6>();
|
|
}
|
|
|
|
public ZorroT6ArrayBuilder Add(DateTime time, float high, float low, float open, float close, float additionalValue1, float additionalValue2)
|
|
{
|
|
_items.Add(new ZorroT6(time, high, low, open, close, additionalValue1, additionalValue2));
|
|
return this;
|
|
}
|
|
|
|
public ZorroT6ArrayBuilder Add(double oaDate, float high, float low, float open, float close, float additionalValue1, float additionalValue2)
|
|
{
|
|
_items.Add(new ZorroT6(oaDate, high, low, open, close, additionalValue1, additionalValue2));
|
|
return this;
|
|
}
|
|
|
|
public ZorroT6ArrayBuilder Add(ZorroT6 item)
|
|
{
|
|
_items.Add(item);
|
|
return this;
|
|
}
|
|
|
|
public ZorroT6[] ToArray() => _items.ToArray();
|
|
public void Clear() => _items.Clear();
|
|
public int Count => _items.Count;
|
|
|
|
public void SaveToFile(string filePath)
|
|
{
|
|
ZorroT6.SaveToFile(filePath, _items.ToArray());
|
|
}
|
|
}
|
|
} |