Passed
Push — master ( 7077b7...c50ccd )
by Alec
02:59
created

VolumeCounter::reset()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * User: alec
4
 * Date: 19.11.18
5
 * Time: 17:27
6
 */
7
declare(strict_types=1);
8
9
namespace AlecRabbit\Counters;
10
11
use AlecRabbit\Structures\Trade;
12
13
class VolumeCounter extends EventsCounter
14
{
15
    protected const DOMAINS = [
16
        STR_TOTAL,
17
        STR_SELL,
18
        STR_BUY,
19
        STR_VP_TOTAL,
20
        STR_VP_SELL,
21
        STR_VP_BUY,
22
        STR_P_SUM_TOTAL,
23
        STR_P_SUM_SELL,
24
        STR_P_SUM_BUY,
25
    ];
26
27
    /** @var array */
28
    protected $volumes = [];
29
30 3
    public function addTrade(Trade $trade): void
31
    {
32 3
        $baseTimes = $this->getBaseTimes($trade->timestamp);
33 3
        $volumePrice = $trade->amount * $trade->price;
34 3
        foreach ($baseTimes as $period => $timestamp) {
35 3
            $this->processPart(STR_TOTAL, $period, $timestamp, $volumePrice, $trade);
36 3
            if ($trade->side === T_SELL) {
37 3
                $this->processPart(STR_SELL, $period, $timestamp, $volumePrice, $trade);
38
            } else {
39 3
                $this->processPart(STR_BUY, $period, $timestamp, $volumePrice, $trade);
40
            }
41 3
            $this->trim($period);
42
        }
43 3
    }
44
45
    /**
46
     * @param string $subdomain
47
     * @param int $period
48
     * @param int $timestamp
49
     * @param float $volumePrice
50
     * @param Trade $trade
51
     */
52 3
    protected function processPart(
53
        string $subdomain,
54
        int $period,
55
        int $timestamp,
56
        float $volumePrice,
57
        Trade $trade
58
    ): void {
59 3
        $this->volumes[STR_VP . $subdomain][$period][$timestamp] =
60 3
            $this->volumes[STR_VP . $subdomain][$period][$timestamp] ?? 0;
61 3
        $this->volumes[STR_VP . $subdomain][$period][$timestamp] += $volumePrice;
62
63 3
        $this->volumes[STR_P_SUM . $subdomain][$period][$timestamp] =
64 3
            $this->volumes[STR_P_SUM . $subdomain][$period][$timestamp] ?? 0;
65 3
        $this->volumes[STR_P_SUM . $subdomain][$period][$timestamp] += $trade->price;
66
67 3
        $this->volumes[$subdomain][$period][$timestamp] = $this->volumes[$subdomain][$period][$timestamp] ?? 0;
68 3
        $this->volumes[$subdomain][$period][$timestamp] += $trade->amount;
69
70 3
        $this->data[$subdomain][$period][$timestamp] = $this->data[$subdomain][$period][$timestamp] ?? 0;
71 3
        $this->data[$subdomain][$period][$timestamp]++;
72 3
    }
73
74
    /**
75
     * @param int $period
76
     */
77 3
    protected function trim(int $period): void
78
    {
79 3
        $threshold = $this->getThreshold($period);
80 3
        foreach (static::DOMAINS as $domain) {
81 3
            if (null !== ($key = array_key_first($this->data[$domain][$period] ?? [])) && ($key <= $threshold)) {
82 2
                unset($this->data[$domain][$period][$key]);
83
            }
84 3
            if (null !== ($key = array_key_first($this->volumes[$domain][$period] ?? [])) && ($key <= $threshold)) {
85 3
                unset($this->volumes[$domain][$period][$key]);
86
            }
87
        }
88 3
    }
89
90
    /**
91
     * @param bool|null $reset
92
     * @return array
93
     */
94 4
    public function getVolumeArray(?bool $reset = null): array
95
    {
96 4
        $volume = [];
97 4
        foreach (static::DOMAINS as $domain) {
98 4
            foreach ($this->periods as $period => $groupBy) {
99 4
                if (0 < ($sum = array_sum($this->volumes[$domain][$period] ?? []))) {
100 4
                    $volume[$domain][$period] = $sum;
101
                }
102
            }
103
        }
104 4
        $events = $this->getEventsArray();
105 4
        foreach ($this->periods as $period => $groupBy) {
106 4
            if (isset($volume[STR_VP_TOTAL][$period], $volume[STR_TOTAL][$period])) {
107 3
                $volume[STR_VWAP_TOTAL][$period] = $volume[STR_VP_TOTAL][$period] / $volume[STR_TOTAL][$period];
108
            }
109 4
            if (isset($volume[STR_VP_SELL][$period], $volume[STR_SELL][$period])) {
110 3
                $volume[STR_VWAP_SELL][$period] = $volume[STR_VP_SELL][$period] / $volume[STR_SELL][$period];
111
            }
112 4
            if (isset($volume[STR_VP_BUY][$period], $volume[STR_BUY][$period])) {
113 3
                $volume[STR_VWAP_BUY][$period] = $volume[STR_VP_BUY][$period] / $volume[STR_BUY][$period];
114
            }
115 4
            if (isset($volume[STR_P_SUM_TOTAL][$period], $events[STR_TOTAL][$period])) {
116 3
                $volume[STR_AVG_PRICE_TOTAL][$period] =
117 3
                    $volume[STR_P_SUM_TOTAL][$period] / $events[STR_TOTAL][$period];
118
            }
119 4
            if (isset($volume[STR_P_SUM_SELL][$period], $events[STR_SELL][$period])) {
120 3
                $volume[STR_AVG_PRICE_SELL][$period] =
121 3
                    $volume[STR_P_SUM_SELL][$period] / $events[STR_SELL][$period];
122
            }
123 4
            if (isset($volume[STR_P_SUM_BUY][$period], $events[STR_BUY][$period])) {
124 3
                $volume[STR_AVG_PRICE_BUY][$period] =
125 4
                    $volume[STR_P_SUM_BUY][$period] / $events[STR_BUY][$period];
126
            }
127
        }
128 4
        if ($reset) {
129 1
            $this->reset();
130
        }
131 4
        return $volume;
132
    }
133
134
    /**
135
     * @inheritDoc
136
     */
137 4
    public function getEventsArray(?bool $reset = null): array
138
    {
139 4
        $events = [];
140 4
        foreach (static::DOMAINS as $domain) {
141 4
            foreach ($this->periods as $period => $groupBy) {
142 4
                if (0 < ($sum = array_sum($this->data[$domain][$period] ?? []))) {
143 4
                    $events[$domain][$period] = $sum;
144
                }
145
            }
146
        }
147 4
        if ($reset) {
148
            $this->reset();
149
        }
150 4
        return $events;
151
    }
152
153
    /**
154
     * @inheritDoc
155
     */
156 1
    protected function reset(): void
157
    {
158 1
        $this->data = [];
159 1
        $this->volumes = [];
160 1
    }
161
162
    /** @return array */
163 3
    public function getRawData(): array
164
    {
165
        return
166
            [
167 3
                STR_VOLUMES => $this->volumes,
168 3
                STR_EVENTS => parent::getRawData(),
169
            ];
170
    }
171
}
172