Completed
Push — master ( 7d146f...c413e2 )
by Rafael S.
01:21
created

prorate_commissions()   A

Complexity

Conditions 4

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 6
Bugs 0 Features 1
Metric Value
cc 4
dl 0
loc 11
rs 9.2
c 6
b 0
f 1
1
"""Tasks for the OperationContainer.
2
3
trade: Financial Application Framework
4
http://trade.readthedocs.org/
5
https://github.com/rochars/trade
6
License: MIT
7
8
Copyright (c) 2016 Rafael da Silva Rocha
9
10
Permission is hereby granted, free of charge, to any person obtaining a copy
11
of this software and associated documentation files (the "Software"), to deal
12
in the Software without restriction, including without limitation the rights
13
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
copies of the Software, and to permit persons to whom the Software is
15
furnished to do so, subject to the following conditions:
16
17
The above copyright notice and this permission notice shall be included in
18
all copies or substantial portions of the Software.
19
20
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26
THE SOFTWARE.
27
"""
28
29
from __future__ import division
30
31
from . utils import (
32
    merge_operations,
33
    daytrade_condition
34
)
35
from . occurrences import Daytrade
36
37
38
def find_volume(container):
39
    """Find the volume of the operations in the container."""
40
    container.context['volume'] = sum(
41
        operation.volume for operation in container.operations
42
    )
43
44
45
def group_positions(container):
46
    """Group the container operations with the same asset."""
47
    if 'positions' not in container.context:
48
        container.context['positions'] = {}
49
    for operation in container.operations:
50
        if operation.quantity != 0 and operation.update_container:
51
            add_to_position_group(container, operation)
52
53
54
def add_to_position_group(container, operation):
55
    """Adds an operation to the common operations list."""
56
    if 'operations' not in container.context['positions']:
57
        container.context['positions']['operations'] = {}
58
    if operation.subject.symbol in container.context['positions']['operations']:
59
        merge_operations(
60
            container.context['positions']\
61
                ['operations'][operation.subject.symbol],
62
            operation
63
        )
64
    else:
65
        container.context['positions']\
66
            ['operations'][operation.subject.symbol] = operation
67
68
69
def fetch_daytrades(container):
70
    """An OperationContainer task.
71
72
    Fetches the daytrades from the OperationContainer operations.
73
74
    The daytrades are placed on the container positions under the
75
    'daytrades' key, inexed by the Daytrade asset's symbol.
76
    """
77
    for i, operation_a in enumerate(container.operations):
78
        for operation_b in [
79
                x for x in container.operations[i:] if\
80
                    daytrade_condition(x, operation_a)
81
            ]:
82
            Daytrade(operation_a, operation_b).append_to_positions(container)
83
84
85
def prorate_commissions(container):
86
    """Prorates the container's commissions by its operations.
87
88
    This method sum the discounts in the commissions dict of the
89
    container. The total discount value is then prorated by the
90
    position operations based on their volume.
91
    """
92
    if 'positions' in container.context:
93
        for position_value in container.context['positions'].values():
94
            for position in position_value.values():
95
                prorate(container, position)
96
97
98
def prorate(container, position):
99
    """Prorate the commissions for one position."""
100
    if position.update_position:
101
        prorate_commissions_by_position(container, position)
102
    else:
103
        for operation in position.operations:
104
            prorate_commissions_by_position(container, operation)
105
106
107
def prorate_commissions_by_position(container, operation):
108
    """Prorates the commissions of the container for one position.
109
110
    The ratio is based on the container volume and the volume of
111
    the position operation.
112
    """
113
    if 'volume' in container.context:
114
        if operation.volume != 0 and container.context['volume'] != 0:
115
            percent = operation.volume / container.context['volume'] * 100
116
            for key, value in container.commissions.items():
117
                operation.commissions[key] = value * percent / 100
118