What is a strategy for scalping?
It sounds complicated, but that is not the whole idea. Imagine yourself at a market, spotting possibilities to purchase goods at one price and then rapidly resell them to someone else for a marginally higher price. That is essentially the essence of scalping in trading: it is the process of quickly realizing minor profits by seizing upon minute changes in market price.
You may have already noticed an issue with this, and you would be correct. Transaction fees are assessed by exchanges. Even if the deal is profitable, you risk losing money if you don't use high frequency trading into your plan because of its sometimes expensive fees. I'll demonstrate how to handle this for you.
Now, picture yourself trading cryptocurrencies in a lightning-fast online market when we discuss applying this to Bitcoin trading in particular. Scalping is ideal for cryptocurrencies like Bitcoin since their prices can fluctuate significantly, even in a little period of time. You purchase some Bitcoin, which you subsequently sell for a slight profit as soon as its value slightly increases. After that, you repeat the process numerous times each day.
As you might expect, for this function effectively, you must trade utilizing a short interval. As scalping aims to profit from little market fluctuations within a very short timescale, traders frequently use short time frames, such as 1-minute, 5-minute, or 15-minute intervals. Scalpers love the 1-minute period because it allows them to capture a lot of tiny price fluctuations that happen during a trading day. However, a trader's particular approach, risk tolerance, and the market they are trading on can all influence the timeframe they choose. I'm going to use 1-minute data from the EODHD APIs for my presentation.
Benefits of Scalping Bitcoin Quick Profits: You can earn a respectable number of little victories throughout the day if you're quick and observant. PyCryptoBot, a cryptocurrency trading bot I created, is ideal for automating this. Another option would be to utilize a websocket.
Excitement: It's quite exhilarating! You always have your eyes open for new prospects and act quickly.
Utilizing Leverage: Leverage is a tool used by certain traders to increase their trading power and possibly increase earnings from modest market movements, however bitcoin exchanges are usually exempt from this. On social media sites like Instagram, you can accomplish this, but you must have a professional account and be aware of the serious risks involved.
Cons of Scalping Bitcoin: High danger: While there is a chance for profit, there is also a high danger, particularly when utilizing leverage because losses can be compounded.
Fees May Build Up: There are fees associated with each trade you make. These could reduce your earnings or even make a winning strategy lose if you're not attentive. The strategic logic must take the fees into account.
Frequent and Exhausting: It's not precisely carefree. It is an intense approach to trade because you have to be alert all the time.
Speaking of fees, you should definitely account for them in your calculations. Each time you transact, a little fee is taken by the exchange. Scalping entails making a lot of trades, which entails a lot of little expenses. If you're not paying attention, it can be compared to dying from a thousand wounds. In order to cover these costs as well as turn a profit, the price must fluctuate sufficiently. If not, you can find yourself losing money or running very quickly just to keep where you are. Yes, I know I keep talking about fees, but I can't emphasize how important they are enough.
In summary, because of its volatility, scalping Bitcoin can be thrilling and lucrative, but it's not for the timid. You must be mindful of the hazards, especially how costs may affect your trading approach. It's similar to engaging in a high-stakes computer game with real money at stake. You need to be really disciplined, have a solid plan, and maintain composure.
Overview of the Strategy
Data duration: one minute.
Buy Signal: An upward momentum is indicated when the fast SMA (5 periods) crosses over the slow SMA (12 periods). We purchase at the signal candle's closing price.
Sell Signal: A downward momentum is indicated when the fast SMA (5 periods) crosses below the slow SMA (12 periods). At the signal candle's closure price, we sell.
Exchange Charges: Assume that each trade will include a round-trip (buy and sell) exchange cost. Assume that Coinbase Advanced Trade takes 0.6% of the transaction costs.
Reinvesting: We allocate all earnings from every transaction, encompassing any residual funds after deducting the transaction costs.
Execution: After receiving a signal, the strategy will execute at the closing price.
Initial Investment: A predetermined sum will be invested at the beginning of the backrest.
Obtaining facts to utilize in my work
I will obtain BTC-USD data every minute via EODHD APIs.
Import API Client import pandas as paid from eodhd import config as cfg
API Client (cfg. API_KEY) = API
Define the function get_ohlc_data () and set DF to api. get_historical_data ("BTC-USD. CC", "1m", results=120)
Go back to DF
If "main" is equal to name, then DF = get_ohlc_data ()
pd.to_numeric(df["close"], errors="coerce") = df["close"]
df["close"] df.dropna(subset=["close"], inplace=True).Fillna(value=df["close"]).inplace=True, mean ()
Print (DF)
Using a fundamental tactic
An illustration of a simple scalping technique is this. Adjusting it to perfection will be highly advised. Next, I'll walk you through the process of backtesting this so you can see how your refinement affects the outcome.
slow_sma_period = 12 and fast_sma_period = 5.
DF ["close"]. Rolling (window=fast_sma_period) = df ["fast_sma"]. Mean ()
"slow_sma"[df] = "close" rolling (slow_sma_period. window). Mean ()
#default df["signal"] = 0
DF. LocBuy signal: [df["fast_sma"] > df["slow_sma"], "signal"] = 1.
DF. LocSell signal = [df["fast_sma"] < df["slow_sma"], "signal"] = -1
Print (DF)
The method is being backtested with fee_percent = 0.006 # 0.6%.
starting_investment = 1000.0 cash = starting_investment position = 0 #balance of bitcoins
in range(1, len(df)) for i:
provided that both df.iloc[i]["signal"] == 1 and df.iloc[i - 1]["signal"] == -1:
#purchase, supposing full payment of cash
cash * (1 - fee_percent) = buy_amount # subtract fee / df.iloc[i]["close"] position = buy_amount
cash is equal to 0.
elif both df.iloc[i - 1] and df.iloc[i]["signal"] == -1["signal"] == 1
#sell, turning position into cash cash = position * df.iloc[i]["close"] * (1 - fee_percent) #subtract fee; position = 0.
final_value is equivalent to cash. position * df.iloc[-1] if position == 0 else["close"]
final value - initial investment equals net result.
print(f"Final Amount: {final_value:.2f}")
print(f"Net Result: {net_result:.2f} ({net_result / initial_investment * 100:.2f}%)")
This demonstrates that the method would be unsuccessful when employing 120 minutes of data. In 120 minutes, the initial £1000 investment would drop to £914.38. A net result of -8.56%, or -£85.62. This is not at all surprising. The technique accounts for the extremely high fees charged by Coinbase.
When fees are subtracted from the calculation, the outcome is positive.
0.006 # fee_percent = 0.6%
percentage_fee = 0.0 # 0.0%
0.08% after two hours.
Trailing Stop Loss and Profit Calculation
Implementing a trailing stop loss and/or a take-profit mechanism is one possible technique to improve this while keeping fees included. Typically, the take-profit is thrice the stop loss.
After some trial and error, I was able to get a good outcome, however I had to reduce the costs from 0.6% to 0.1%. With something as volatile as Bitcoin, anything higher than this doesn't seem to be consistent, at least not for one-minute intervals.
Additionally, I switched from SMA crossovers to EMA crossovers, which are more responsive and ideal when working with cryptocurrency.
This is how my code appears:
slow_ma_period = 26 and fast_ma_period = 12.
df["close"] = df["fast_ma"].window=fast_ma_period is rolling.df["slow_ma"] # df["close"] = mean()..rolling(slow_ma_period window).df["fast_ma"] = df["close"] = mean()..ewm(adjust=False, span=fast_ma_period).mean() df["slow_ma"].ewm(span=slow_ma_period, adjust=False) = df["close"].mean()
#default df["signal"] = 0
df.locBuy signal: [df["fast_ma"] > df["slow_ma"], "signal"] = 1.
df.locSell signal = [df["fast_ma"] < df["slow_ma"], "signal"] = -1
fee_percent = 0.1% #0.001
first_investment is set at 1000.Initial investment position = 0 high since purchase = 0 buy price = 0 and cash = 0
For example, trailing_stop_loss = 0.002 × 100 = 0.2%
trailing_stop_loss * 3 = take_profit # 3x trailing stop loss stop_loss = 0.02 # For example, 0.02 × 100 = 2%
current_price = DF. Yolk[i] for me in range (1, len(df))["close"]
When position is greater than zero, high_since_buy = max (high_since_buy, current_price) if current_price is less than or equal?
to high_since_buy (1 - trailing_stop_loss): cash = position current price (1 - fee_percent)} position = 0 high_since_buy = 0 print(f) "Trailing stop loss activated at {current_price}, cash now {cash}")
If buy_price (1 + take_profit) >= current_price, then cash = position current_price (1 - percentage of fee)
position = 0, high_since_buy = 0, print(f) "Take profit activated at {current_price}, cash now {cash}") elif current_price <= buy_price (1 - stop_loss): cash = position current_price * (1 - fee_percent) position = 0 high_since_buy = 0 print (f,"Stop loss activated at {current_price}, cash now {cash}")
If cash > 0, then buy_amount = cash * (1 - fee_percent) for both DF. Yolk[i] ["signal"] == 1 and df.iloc[i - 1]["signal"]!= 1.
buy_amount / current_price = position
Money = 0 high_since_buy = current_price
Current price minus buy price
Print(f) "Bought at {current_price}, position now {position}")
If position is more than zero, then cash is equal to position current_price (1 - fee_percent). Elsewise, def. Yolk[i] ["signal"] == -1 and df.iloc[i - 1]["signal"]!= -1.
Position = 0 high_since_buy = 0 print(f) "Sold at {current_price}, cash now {cash}")
final_value is equivalent to cash. Position * df.iloc[-1] if position == 0 else["close"]
final value - initial investment equals net result.
print (f,"Final Amount: {final_value:. 2f}")
print (f,"Net Result: {net_result:. 2f} ({net_result / initial_investment * 100:. 2f} %)")
This is the outcome of it.
Purchased in 64034.67; currently trading at 0.015600923687121368,
@ 63988.53; cash on hand is now 997.2818932076951.
Purchased in 64011.68; currently trading at 0.015564106602333939
Profit at 64431.99; Pay 1001.8235345995538 at this time.
Purchased for 64399.0; current position is 0.015540951118261995
Paying out at 64606.62, trailing stop loss at 1003.0442750127916.
Total Amount: 1003.04
Final Score: 3.04 (0.30%)
Automation: Websocket or Bot
For something to be effective, it is ideal to automate. It would be nearly hard to do all of the analysis and updates manually without making mistakes given the short turnaround time.
I was investigating websocket-based solutions for this. The documentation for the websocket API for bitcoin provided by EODHD APIs is available here.
I figured I would give you a little code to get you going.
import websocket, import datetime, import time, import threading, import signal, and import configuration as cfg.
last printed minute = None; data = {}
fun on_message(ws, message): message_json = json.loads(message); global last_printed_minute
If "t" exists in message_json, then date_time = message_json["t"] / 1000.0 datetime.datetime.utcfromtimestamp
date_time.replace(second=0, microsecond=0) = floored_datetime
floored_datetime.isoformat() iso_format =
If the iso_format not found in the data
data[iso_format] = {"count": 1}, "sum": float(message_json["p"])
Alternatively:
Data [iso_format] float (message_json ["p"]) += ["sum"]
Data [iso_format] ["count"] += 1
If iso_format! = last_printed_minute, then
Should last_printed_minute not be None at all: avg_price = (data [last_printed_minute],["sum"] data [last printed minute] / data[sum"This is ["acount"]
Print (f "{minute_last_printed}: Pricing average: {avg_price}") last_printed_minute = iso_format
Print ("Error:" + str (error)) is the def on_error (ws, error) method.
Print ("WebSocket closed") is the result of def on_close (ws, close_status_code, close_msg).
Define on_open (ws) as follows: def run (*args): payload = {"action": "subscribe", "symbols": "BTC-USD",}
W's. Send (payload, json. dumps)
# remain alive as long as True: time. W's. Send (json. dumps ({"action": "keep_alive"})) sleep(50)
Threading = thread. Thread. Start () Thread (target=run)
Print ("Signal received, closing WebSocket...") ws. Close () is the definition of def on_signal (signal, frame).
If "main" is the value of name, then websocket. EnableTrace (False)
Websocket = ws. WebSocketApp (f,"wss: //ws. Pen, on_message=on_message, on_error=on_error,).
Signal. Signal (on_signal, signal. SIGINT) #manage the Ctrl-C key. Signal (signal. SIGTERM, on_signal) # execute commands to terminate
W's. run_forever ()
By connecting to the websocket, this code will subscribe to the BTC-USD messages. After that, it will compile all of the data into a minute, determine the minutely average price, and correlate that figure with the ISO-formatted minute timestamp. In addition, it features a stay alive function to maintain the web socket open and a graceful shutdown mechanism in case the script ends.
You'll ultimately have something that resembles this...
2024-04-14T20:26:00: 64106.09294307696 is the average price.
2024-04-14T20:27:00: 64108.821365536765 is the average price.
2024-04-14T20:28:00: 64137.0758961011 is the average price.
2024-04-14T20:29:00: 64134.83291021914 is the average price.
2024-04-14T20:30:00: 64162.79143044936 is the average price.
2024-04-14T20:31:00: 64212.15334335508 is the average price.
I'm using the EMA12 and EMA26 in the scalping code I mentioned earlier. This indicates that in order to compute the EMA26, which is necessary to compute the buy/sell signal, the websocket must be operated for 26 minutes.
From now on, the procedure remains the same. You would just recalculate the moving averages as soon as the websocket returns the following minute, and then decide what to do with the outcome.
In summary
Yes, a scalping approach can work. It would be quite desirable to use a websocket or bot to automate the procedure. If you did this by hand, you would quickly have gray hair. Additionally, you should look for an exchange with extremely cheap rates or a different pricing schedule. Binance is a decent option because of their significantly cheaper costs.
I hope this essay was helpful and interesting to you. Don't forget to follow me and subscribe to my email notifications if you want to be updated.