-
Notifications
You must be signed in to change notification settings - Fork 1
/
43-finding-arbitrage-opportunity(copper).go
90 lines (73 loc) · 2.92 KB
/
43-finding-arbitrage-opportunity(copper).go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/*
Copper.co - Interview
The task typically involves identifying arbitrage opportunities in currency exchange rates. Arbitrage involves exploiting the price differences of currencies in different markets to make a profit. This would involve:
Finding a Currency Conversion Cycle: That results in more of the original currency than you started with after completing a series of trades starting and ending with the same currency.
Calculation: Multiply the exchange rates for a cycle of currency conversions. If the product of these rates exceeds 1 when you return to the original currency, an arbitrage opportunity exists.
example:
GBP -> USD -> EUR -> GBP
[2 0 1 2] 1.012 --- (Round) ---> 1.01
USD: {USD: 1.00, EUR: 0.92, GBP: 0.79, CHF: 0.89},
EUR: {USD: 1.09, EUR: 1.00, GBP: 0.86, CHF: 0.90},
GBP: {USD: 1.28, EUR: 1.19, GBP: 1.00, CHF: 1.13},
CHF: {USD: 1.13, EUR: 1.04, GBP: 0.88, CHF: 1.00},
*/
/*
Basic Concept:
- Select a Currency: Start from one currency.
- Find Cycles: Explore all cycles starting and ending at this currency.
- Calculate Product: Multiply the exchange rates for each cycle.
- Check for Arbitrage: If the product of the rates in any cycle is greater than 1, it indicates an arbitrage opportunity.
Explanation:
- checkArbitrage Function: This function recursively checks for cycles starting from a specific currency. It multiplies the exchange rates as it traverses through the cycle and checks if the product exceeds 1 when it completes the cycle.
- findArbitrage Function: This iterates over each currency and uses checkArbitrage to detect any arbitrage starting from each.
- Depth: A depth check is included to avoid infinite recursion and only allow revisiting the start currency when completing a cycle.
*/
package main
import (
"fmt"
)
type Currency string
const (
USD Currency = "USD"
EUR Currency = "EUR"
GBP Currency = "GBP"
CHF Currency = "CHF"
)
var exchange = map[Currency]map[Currency]float64{
USD: {EUR: 0.92, GBP: 0.79, CHF: 0.89},
EUR: {USD: 1.09, GBP: 0.86, CHF: 0.90},
GBP: {USD: 1.28, EUR: 1.19, CHF: 1.13},
CHF: {USD: 1.13, EUR: 1.04, GBP: 0.88},
}
// Check for arbitrage starting from a specific currency
func checkArbitrage(start Currency, current Currency, product float64, visited map[Currency]bool, depth int) bool {
if depth > 0 && current == start {
return product > 1.0 // Arbitrage condition
}
visited[current] = true
for next, rate := range exchange[current] {
if !visited[next] || (depth > 0 && next == start) {
if checkArbitrage(start, next, product*rate, visited, depth+1) {
return true
}
}
}
visited[current] = false
return false
}
func findArbitrage() bool {
for currency := range exchange {
visited := make(map[Currency]bool)
if checkArbitrage(currency, currency, 1.0, visited, 0) {
return true
}
}
return false
}
func main() {
if findArbitrage() {
fmt.Println("Arbitrage opportunity detected!")
} else {
fmt.Println("No arbitrage opportunity found.")
}
}