File size: 4,906 Bytes
05a7335
77198ce
05a7335
77198ce
2dee41b
 
 
 
 
 
 
 
 
05a7335
2dee41b
05a7335
 
2dee41b
 
 
 
 
 
05a7335
 
 
 
 
 
2dee41b
 
05a7335
2dee41b
05a7335
 
2dee41b
 
 
 
 
 
 
 
 
 
 
 
05a7335
2dee41b
05a7335
 
 
 
 
 
 
2dee41b
05a7335
2dee41b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
05a7335
2dee41b
05a7335
 
 
 
 
 
 
 
2dee41b
 
 
 
 
 
 
 
 
05a7335
 
 
 
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import gradio as gr
import asyncio
from triangular_arbitrage import detector

async def run_detection_ui(
    exchange_name,
    include_fees,
    use_taker,
    trade_size_usd,
    slippage_factor,
    api_key,
    api_secret
):
    try:
        best_opps, best_profit, fee_breakdown = await detector.run_detection(
            exchange_name=exchange_name,
            max_cycle=3,  # fixed triangular only
            include_fees=include_fees,
            use_taker=use_taker,
            trade_size_usd=trade_size_usd,
            slippage_factor=slippage_factor,
            api_key=api_key if api_key else None,
            api_secret=api_secret if api_secret else None,
        )

        if not best_opps:
            return "No arbitrage opportunity found."

        result_lines = []
        result_lines.append("## Trading Cycle:")
        for i, ticker in enumerate(best_opps, 1):
            result_lines.append(
                f"{i}. {ticker.symbol} | price: {ticker.last_price:.8f}"
            )

        result_lines.append("\n## Profit Analysis:")
        
        if include_fees and fee_breakdown:
            result_lines.append(f"**Gross Profit:** {fee_breakdown['gross_profit']*100:.4f}%")
            result_lines.append(f"**Trading Fees:** {fee_breakdown['total_fees']*100:.4f}% ({fee_breakdown['fee_rate_per_trade']*100:.2f}% per trade)")
            result_lines.append(f"**Slippage:** {fee_breakdown['total_slippage']*100:.4f}% ({fee_breakdown['slippage_per_trade']*100:.4f}% per trade)")
            result_lines.append(f"**Net Profit:** {fee_breakdown['net_profit']*100:.4f}%")
            result_lines.append(f"\n**Net Profit Multiplier:** {best_profit:.8f}")
        else:
            result_lines.append(f"**Gross Profit:** {(best_profit - 1)*100:.4f}%")
            result_lines.append(f"**Profit Multiplier:** {best_profit:.8f}")
            result_lines.append("\n*Note: Fees and slippage not included. Enable 'Include Fees' to see net profit.*")

        return "\n".join(result_lines)

    except Exception as e:
        return f"Error while scanning: {str(e)}"


with gr.Blocks(title="Triangular Arbitrage Scanner") as demo:
    gr.Markdown("# Triangular Arbitrage Scanner")
    gr.Markdown("Scan for triangular arbitrage opportunities with fee and slippage calculations.")

    with gr.Row():
        with gr.Column():
            exchange = gr.Dropdown(
                choices=[
                    "binanceus",
                    "binance",
                    "huobi",
                    "htx",
                ],
                value="binanceus",
                label="Exchange",
            )
            
            include_fees = gr.Checkbox(
                value=True,
                label="Include Fees & Slippage",
                info="Calculate net profit after trading fees and slippage"
            )
            
            use_taker = gr.Radio(
                choices=[("Taker Fees", True), ("Maker Fees", False)],
                value=True,
                label="Fee Type",
                info="Taker fees are typically higher but execute immediately"
            )
            
            trade_size_usd = gr.Slider(
                minimum=100,
                maximum=100000,
                value=1000,
                step=100,
                label="Trade Size (USD)",
                info="Estimated trade size for slippage calculation"
            )
            
            slippage_factor = gr.Slider(
                minimum=0.0001,
                maximum=0.002,
                value=0.0005,
                step=0.0001,
                label="Slippage Factor",
                info="Slippage per $1000 traded (0.0005 = 0.05% per $1000)"
            )
        
        with gr.Column():
            gr.Markdown("### API Keys (Optional)")
            gr.Markdown("Provide API keys to fetch your actual fee tier (VIP discounts, etc.)")
            
            api_key = gr.Textbox(
                label="API Key",
                type="password",
                placeholder="Enter your API key (optional)",
                info="Used to fetch your actual fee tier"
            )
            
            api_secret = gr.Textbox(
                label="API Secret",
                type="password",
                placeholder="Enter your API secret (optional)",
                info="Used to fetch your actual fee tier"
            )

    scan_btn = gr.Button("Scan for opportunities", variant="primary", size="lg")

    output = gr.Markdown(
        value="Select exchange and click **Scan**.",
        label="Result"
    )

    scan_btn.click(
        fn=run_detection_ui,
        inputs=[
            exchange,
            include_fees,
            use_taker,
            trade_size_usd,
            slippage_factor,
            api_key,
            api_secret
        ],
        outputs=output,
    )

demo.launch()