Initial commit
This commit is contained in:
@@ -0,0 +1,286 @@
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user