Skip to content

Commit 3008af0

Browse files
docs
1 parent 216a84a commit 3008af0

File tree

8 files changed

+131
-317
lines changed

8 files changed

+131
-317
lines changed

common/account.go

+24-1
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,24 @@ import (
66
"github.com/quick-trade/xoney/internal"
77
)
88

9+
// BaseDistribution represents a user's balance on an exchange in the base currency.
10+
// It maps each currency to the corresponding quantity, allowing for the representation
11+
// of the entire portfolio in a unified manner.
912
type BaseDistribution map[data.Currency]float64
1013

14+
// Portfolio holds the financial position of a user on exchange
15+
// and the main currency of valuation. It provides methods to manipulate and
16+
// evaluate the asset distribution.
1117
type Portfolio struct {
12-
assets BaseDistribution
18+
// assets holds the distribution of different currencies and their quantities.
19+
assets BaseDistribution
20+
// mainCurrency is the primary currency used for valuation of the portfolio.
1321
mainCurrency data.Currency
1422
}
1523

24+
// Calculates the total value of the portfolio in the main currency.
25+
// It takes a map of prices where each currency is mapped to its current price in the main currency.
26+
// The function returns the total as a float64 and an error if any currency in the portfolio doesn't have a corresponding price.
1627
func (p Portfolio) Total(prices map[data.Currency]float64) (float64, error) {
1728
total := 0.0
1829
err := errors.NewMissingCurrencyError(internal.DefaultCapacity)
@@ -39,30 +50,42 @@ func (p Portfolio) Total(prices map[data.Currency]float64) (float64, error) {
3950
return total, err
4051
}
4152

53+
// Balance returns the amount of the specified currency held in the portfolio.
4254
func (p Portfolio) Balance(currency data.Currency) float64 {
4355
return p.assets[currency]
4456
}
57+
// Assets returns a reference to the current assets held in the portfolio.
58+
// Be cautious when using this reference directly as it can alter the portfolio's state.
59+
// Consider using .Copy() method for a safe, mutable copy if needed.
4560
func (p Portfolio) Assets() BaseDistribution { return p.assets }
4661

62+
// Set assigns the specified quantity of a currency to the portfolio.
4763
func (p *Portfolio) Set(currency data.Currency, quantity float64) {
4864
p.assets[currency] = quantity
4965
}
5066

67+
// Increase adds the specified quantity of a currency to the portfolio.
5168
func (p *Portfolio) Increase(currency data.Currency, quantity float64) {
5269
p.assets[currency] += quantity
5370
}
5471

72+
// Decrease subtracts the specified quantity of a currency from the portfolio.
5573
func (p *Portfolio) Decrease(currency data.Currency, quantity float64) {
5674
p.assets[currency] -= quantity
5775
}
76+
77+
// Returns the main currency used for the valuation of the portfolio.
5878
func (p Portfolio) MainCurrency() data.Currency { return p.mainCurrency }
79+
80+
// Creates a deep copy of the portfolio.
5981
func (p Portfolio) Copy() Portfolio {
6082
return Portfolio{
6183
assets: internal.MapCopy(p.assets),
6284
mainCurrency: p.mainCurrency,
6385
}
6486
}
6587

88+
// NewPortfolio creates a new Portfolio with the specified main currency.
6689
func NewPortfolio(mainCurrency data.Currency) Portfolio {
6790
return Portfolio{
6891
assets: make(map[data.Currency]float64, internal.DefaultCapacity),

common/data/candlestick.go

+58-4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
"github.com/quick-trade/xoney/internal"
99
)
1010

11+
// Period is a utility structure used for denoting intervals in time.
12+
// It allows for convenient slicing of various time-series data.
1113
type Period struct {
1214
Start time.Time
1315
End time.Time
@@ -17,12 +19,17 @@ func NewPeriod(start, end time.Time) Period {
1719
return Period{Start: start, End: end}
1820
}
1921

22+
// ShiftedStart returns a new Period with the start time shifted by the given duration.
23+
// The end time of the Period is not affected.
2024
func (p Period) ShiftedStart(shift time.Duration) Period {
2125
p.Start = p.Start.Add(shift)
2226

2327
return p
2428
}
2529

30+
// TimeStamp represents a sequence of time moments.
31+
// These moments are not required to have a constant step between them,
32+
// but the data should be sequential.
2633
type TimeStamp struct {
2734
timeframe TimeFrame
2835
Timestamp []time.Time
@@ -38,11 +45,13 @@ func NewTimeStamp(timeframe TimeFrame, capacity int) TimeStamp {
3845
func (t *TimeStamp) Timeframe() TimeFrame {
3946
return t.timeframe
4047
}
41-
48+
// At returns the time at the specified index within the TimeStamp.
4249
func (t TimeStamp) At(index int) time.Time {
4350
return t.Timestamp[index]
4451
}
4552

53+
// Extend increases the length of the TimeStamp by n timeframes,
54+
// adding new moments sequentially based on the TimeStamp's timeframe.
4655
func (t *TimeStamp) Extend(n int) {
4756
last := t.At(len(t.Timestamp) - 1)
4857
for i := 0; i < n; i++ {
@@ -51,26 +60,36 @@ func (t *TimeStamp) Extend(n int) {
5160
}
5261
}
5362

63+
// Append adds the provided moments to the end of the TimeStamp.
64+
// If you need to extend the TimeStamp by N timeframes, consider using Extend instead.
5465
func (t *TimeStamp) Append(moments ...time.Time) {
5566
t.Timestamp = internal.Append(t.Timestamp, moments...)
5667
}
5768

69+
// Slice returns a new TimeStamp consisting of the time moments within the range [start, stop).
5870
func (t TimeStamp) Slice(start, stop int) TimeStamp {
5971
return TimeStamp{
6072
timeframe: t.timeframe,
6173
Timestamp: t.Timestamp[start:stop],
6274
}
6375
}
6476

77+
// End returns the last time moment within the TimeStamp.
6578
func (t TimeStamp) End() time.Time {
6679
return t.At(len(t.Timestamp) - 1)
6780
}
6881

82+
// Start returns the first time moment within the TimeStamp.
6983
func (t TimeStamp) Start() time.Time {
7084
return t.At(0)
7185
}
86+
87+
// Len returns the number of time moments within the TimeStamp.
7288
func (t TimeStamp) Len() int { return len(t.Timestamp) }
7389

90+
// Candle represents a single candlestick data point in a financial chart,
91+
// encapsulating the open, high, low, close values and the volume of trading
92+
// over a particular time period, with TimeClose marking the end of that period.
7493
type Candle struct {
7594
Open float64
7695
High float64
@@ -90,7 +109,10 @@ func NewCandle(open, high, low, c, volume float64, timeClose time.Time) *Candle
90109
TimeClose: timeClose,
91110
}
92111
}
93-
112+
// InstrumentCandle represents a candlestick data point with an associated financial instrument.
113+
// It combines the detailed candlestick information such as OHLCV with the specific instrument
114+
// for which this data is relevant. This data structure is commonly used in trading strategies
115+
// as the primary source of information from which trading signals are generated.
94116
type InstrumentCandle struct {
95117
Candle
96118
Instrument
@@ -103,6 +125,9 @@ func NewInstrumentCandle(candle Candle, instrument Instrument) *InstrumentCandle
103125
}
104126
}
105127

128+
// Chart represents a sequence of candlestick data points for a specific instrument.
129+
// It contains slices of open, high, low, close values and the trading volume,
130+
// along with the corresponding timestamps for each data point.
106131
type Chart struct {
107132
Open []float64
108133
High []float64
@@ -112,6 +137,9 @@ type Chart struct {
112137
Timestamp TimeStamp
113138
}
114139

140+
// RawChart creates a new Chart with slices preallocated to the specified capacity.
141+
// This function is used to initialize a Chart for a certain timeframe and with a capacity
142+
// hint to optimize memory allocations for the underlying slices.
115143
func RawChart(timeframe TimeFrame, capacity int) Chart {
116144
return Chart{
117145
Open: make([]float64, 0, capacity),
@@ -123,6 +151,9 @@ func RawChart(timeframe TimeFrame, capacity int) Chart {
123151
}
124152
}
125153

154+
// Add appends a single candle to the end of the chart.
155+
// It appends the open, high, low, close, and volume data from the candle
156+
// to their respective slices in the Chart and updates the timestamp.
126157
func (c *Chart) Add(candle Candle) {
127158
c.Open = internal.Append(c.Open, candle.Open)
128159
c.High = internal.Append(c.High, candle.High)
@@ -132,6 +163,10 @@ func (c *Chart) Add(candle Candle) {
132163
c.Timestamp.Append(candle.TimeClose)
133164
}
134165

166+
// Slice returns a new Chart consisting of the candlestick data within the specified period.
167+
// It performs a binary search to find the start and end indices, ensuring O(log N) complexity.
168+
// The resulting slice includes the boundaries of the period. If an exact match for the boundaries
169+
// is not found, the nearest preceding element is included in the slice.
135170
func (c *Chart) Slice(period Period) Chart {
136171
start, err := findIndexBeforeOrAtTime(c.Timestamp, period.Start)
137172
if err != nil {
@@ -152,11 +187,18 @@ func (c *Chart) Slice(period Period) Chart {
152187
Timestamp: c.Timestamp.Slice(start, stop),
153188
}
154189
}
155-
190+
// Len returns the number of timestamps (and hence the number of candles) in the Chart.
156191
func (c *Chart) Len() int {
157192
return len(c.Timestamp.Timestamp)
158193
}
159194

195+
// CandleByIndex retrieves the candle at the specified index from the Chart.
196+
// If the index is out of range, an error is returned.
197+
// Parameters:
198+
// index - The index of the candle to retrieve.
199+
// Returns:
200+
// pointer to a Candle and nil error if successful, or
201+
// nil pointer and an OutOfIndexError if the index is invalid.
160202
func (c *Chart) CandleByIndex(index int) (*Candle, error) {
161203
if index >= c.Len() {
162204
return nil, errors.NewOutOfIndexError(index)
@@ -171,9 +213,12 @@ func (c *Chart) CandleByIndex(index int) (*Candle, error) {
171213
c.Timestamp.At(index),
172214
), nil
173215
}
174-
216+
// ChartContainer represents a collection of instruments and their corresponding charts.
217+
// It can be used to inform your trading system about your investment universe during testing and training.
175218
type ChartContainer map[Instrument]Chart
176219

220+
// ChartsByPeriod slices each chart in the ChartContainer to a new chart based on the provided period.
221+
// It's analogous to the Slice method of the Chart, but it operates on the entire container, slicing each chart.
177222
func (c *ChartContainer) ChartsByPeriod(period Period) ChartContainer {
178223
result := make(ChartContainer, len(*c))
179224
for instrument, chart := range *c {
@@ -183,6 +228,9 @@ func (c *ChartContainer) ChartsByPeriod(period Period) ChartContainer {
183228
return result
184229
}
185230

231+
// FirstStart finds the earliest start time among all charts in the ChartContainer.
232+
// It iterates through all charts and returns the earliest timestamp found.
233+
// If the ChartContainer is empty, it returns the zero value of time.Time.
186234
func (c *ChartContainer) FirstStart() time.Time {
187235
var first time.Time
188236

@@ -196,6 +244,9 @@ func (c *ChartContainer) FirstStart() time.Time {
196244
return first
197245
}
198246

247+
// LastEnd finds the latest end time among all charts in the ChartContainer.
248+
// It iterates through all charts and returns the latest timestamp found.
249+
// If the ChartContainer is empty, it returns the zero value of time.Time.
199250
func (c *ChartContainer) LastEnd() time.Time {
200251
var last time.Time
201252

@@ -226,6 +277,9 @@ func (c *ChartContainer) sortedInstruments() []Instrument {
226277
return keys
227278
}
228279

280+
// Candles returns all the candles in the ChartContainer.
281+
// It implements a merging stage of the merge-sort algorithm.
282+
// Complexity: O(NK), where N is the number of candles and K is the number of instruments.
229283
func (c ChartContainer) Candles() []InstrumentCandle {
230284
// It is just merging from merge-sort algorithm
231285
sumLength := 0

common/data/equity.go

+21-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// Package data provides types and functions for managing financial equity data.
2+
13
package data
24

35
import (
@@ -6,18 +8,26 @@ import (
68
"github.com/quick-trade/xoney/internal"
79
)
810

11+
// Equity represents a financial entity with history of its value and portfolio.
12+
// It tracks the historical and current value of a portfolio along with a timestamp
13+
// for each recorded value.
914
type Equity struct {
10-
portfolioHistory []map[Currency]float64
11-
mainHistory []float64
12-
Timestamp TimeStamp
13-
timeframe TimeFrame
15+
portfolioHistory []map[Currency]float64 // history of portfolio values by currency
16+
mainHistory []float64 // history of main value changes
17+
Timestamp TimeStamp // timestamps corresponding to mainHistory records
18+
timeframe TimeFrame // timeframe for the historical data
1419
}
1520

21+
// Timeframe returns the timeframe of the equity's historical data.
1622
func (e *Equity) Timeframe() TimeFrame {
1723
return e.timeframe
1824
}
1925

26+
// Deposit returns the history of main value changes.
2027
func (e *Equity) Deposit() []float64 { return e.mainHistory }
28+
29+
// PortfolioHistory constructs and returns a history of portfolio values by currency.
30+
// It maps each currency to a slice of its historical values.
2131
func (e *Equity) PortfolioHistory() map[Currency][]float64 {
2232
if len(e.portfolioHistory) == 0 {
2333
return make(map[Currency][]float64)
@@ -40,21 +50,28 @@ func (e *Equity) PortfolioHistory() map[Currency][]float64 {
4050
return result
4151
}
4252

53+
// AddPortfolio appends a new set of portfolio values to the history.
4354
func (e *Equity) AddPortfolio(portfolio map[Currency]float64) {
4455
element := internal.MapCopy(portfolio)
4556
e.portfolioHistory = internal.Append(e.portfolioHistory, element)
4657
}
4758

59+
// AddValue appends a new value to the main history and associates it with a timestamp.
4860
func (e *Equity) AddValue(value float64, timestamp time.Time) {
4961
e.mainHistory = internal.Append(e.mainHistory, value)
5062
e.Timestamp.Append(timestamp)
5163
}
5264

65+
// Now returns the most recent value from the main history.
5366
func (e *Equity) Now() float64 {
5467
return e.mainHistory[len(e.mainHistory)-1]
5568
}
69+
70+
// Start returns the timestamp of the first recorded value in main history.
5671
func (e *Equity) Start() time.Time { return e.Timestamp.At(0) }
5772

73+
// NewEquity creates and returns a new Equity instance with specified timeframe
74+
// and capacity.
5875
func NewEquity(
5976
timeframe TimeFrame,
6077
capacity int,

0 commit comments

Comments
 (0)