orz

趣味のブログです

ボリンジャーバンドで売り買いした場合のシミュレーション (ファーストリテイリングの場合)


前書き

ボリンジャーバンドのロジックで売り買いのやり取りした場合でシミュレーションしてみました。

ボリンジャーバンドのロジックですが、ある特定の期間の移動平均線標準偏差±σ, ±2σを加える。

  • +2σのバンドラインに来たら株を買い、-2σのラインに来たら株を売る (順張りのロジック)
  • -2σのバンドラインに来たら株を買い、+2σのラインに来たら株を売る (逆張りのロジック)

このふたつでシミュレーションするとどうなるかを検証してみました。

準備

10年分の株価を
kabuoji3.com
から引っ張ってきました。

次のプログラムを使って、10年分のcsvを自動取得してみました。

import chromedriver_binary 
from selenium import webdriver
import pyautogui as pg 
import time
#取り出す株コードと年を変数として、取得する
def csv_get(stock_number,year):
    DRIVER_PATH = ("C:\/chromedriver")
    # DRIVER_PATH = '/Users/Kenta/Desktop/Selenium/chromedriver' # ローカル
    # DRIVER_PATH = '/app/.chromedriver/bin/chromedriver'        # heroku

    # ブラウザの起動、銘柄コードと年を受け取って開く(できた)
    driver = webdriver.Chrome(executable_path=DRIVER_PATH)
    driver.get("https://kabuoji3.com/stock/{}/{}/".format(stock_number,year))
    driver.maximize_window()

    #ダウンロードページに移動
    selector = '#base_box > div > div:nth-child(3) > form > button'
    element = driver.find_element_by_css_selector(selector)
    element.click()
    
    selector = '#base_box > div > div.mt_10.tc > form > button'
    element = driver.find_element_by_css_selector(selector)
    element.click()
    
    pg.presskey("Enter")
    print (stock_number,"の",year,"年のcsvデータをダウンロードしました")
for x in range(1997,2021):
    csv_get(9983,x)


このようにして、取得しました。銘柄コードと年数範囲を変えればほかの銘柄にも対応しています。

実際にやってみる

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import openpyxl as px
import copy
from statistics import mean
col_names = ["始値","高値","安値","終値","出来高" ,"終値調整値"] #カラムの名前指定
i = 1 #結合の時に使うダミー変数
#空のデータフレーム作成
df2 = pd.DataFrame(index=[])
#2021年から1997年のデータを全部結合させる, CSVで読み込んだ
for x in range(2021,1997,-1):
    filename ="./9983_"+str(x)+".csv"
    df = pd.read_csv(filename, header = None,names=col_names, encoding ='cp932',skiprows=2)
    if i == 1:
        df2 = copy.copy(df) #copyでデータ転写
    else:
        df2 =pd.concat([df2,df]) #読み込んだdfを結合させる
    i+=1
#プロット用のデータを抜き出す
owarine=[]
day = []
for x in range(len(df2.終値)):
    try:
        owarine.append(int(df2.終値[x])) 
    except:
        continue
owarine.reverse()
day = list(range(0,len(df2.終値),1))

#5日移動平均線
sma5 = []
day_sma5 = day[4:]
for x in range(len(owarine)):
    if (x-4) >= 0:
        sma5 = np.append(sma5,mean(owarine[(x-4):x]))
    else:
        continue

#25日移動平均線と標準偏差の算出
sma25 = []
day_sma25 = day[24:]
std=[]
for x in range(len(owarine)):
    if (x-24) >= 0:
        sma25 = np.append(sma25,mean(owarine[(x-24):x]))
        std = np.append(std,np.std(owarine[(x-24):x]))
    else:
        continue

#125日移動平均線と標準偏差の算出
sma125 = []
day_sma125 = day[124:]
for x in range(len(owarine)):
    if (x-124) >= 0:
        sma125 = np.append(sma125,mean(owarine[(x-124):x]))
    else:
        continue

#ロジックで売り買いしてみる
syuueki =[]#収益を入れる空のリスト
syuueki_g = [] #逆張りした時のリスト
#エクセルを開く。あらかじめセルにキャプションつける
wb = px.Workbook() 
sheet = wb.active
sheet["A1"].value ="ボリンジャーバンドで順張りのやり取りした場合のシミュレーション結果"
sheet["A2"].value ="収益"
sheet["B2"].value ="イベントログ"


sheet["F1"].value ="ボリンジャーバンドで逆張りのやり取りした場合のシミュレーション結果"
sheet["F2"].value ="収益"
sheet["G2"].value ="イベントログ"
count = 1 #イベント変数
count_g =1 #逆張り用のイベント変数
for x in day:
    if x-24>0:
        if owarine[x] > (2*std[x-24]+sma25[x-24]):
            syuueki.append(-1*owarine[x])
            sheet["A"+str(count+2)].value =-1*owarine[x]
            sheet["B"+str(count+2)].value ="株を買いました"
            count += 1
        elif owarine[x] <(-2*std[x-24]+sma25[x-24]):
            syuueki.append(owarine[x])
            sheet["A"+str(count+2)].value =owarine[x]
            sheet["B"+str(count+2)].value ="株を売りました"
            count += 1
        else:
             continue
for x in day:
    if x-24>0:
        if owarine[x] < (-2*std[x-24]+sma25[x-24]):
            syuueki_g.append(-1*owarine[x])
            sheet["F"+str(count_g+2)].value =-1*owarine[x]
            sheet["G"+str(count_g+2)].value ="株を買いました"
            count_g += 1
        elif owarine[x] >(2*std[x-24]+sma25[x-24]):
            syuueki_g.append(owarine[x])
            sheet["F"+str(count_g+2)].value =owarine[x]
            sheet["G"+str(count_g+2)].value ="株を売りました"
            count_g += 1
        else:
             continue
sheet["D3"].value = "順張りの収益の結果"
sheet["D4"].value = sum(syuueki)
sheet["I3"].value = "逆張りの収益の結果"
sheet["I4"].value = sum(syuueki_g)

print ("ファーストリテイリングの銘柄でボリンジャーバンドのロジックでシミュレーションしてみました\n")
print ("順張りロジックなら",count,"回取引しました\n逆張りロジックなら",count_g,"回取引しました")
print ("順張りロジックの合計の収益は",100*sum(syuueki),"円でした\n逆張りロジックの収益は",100*sum(syuueki_g),"円でした")
wb.save("テスト結果.xlsx")

以上のコードを組んで計算してみました。

やってみた結果

出力ですが、以下の画像のようになりました。
順張りの場合と逆張りの場合で正負が逆転していますのが気になりますが、機械的にやりとりして1億の利益・損失が出ているようですね。
f:id:orshibuya0926:20210121220515p:plain

次の課題

  • RSIなどほかのテクニカル手法を組み合わせたシミュレーション
  • ビットコインの値段をリアルタイムで取得して、LINEで通知するプログラム (LINE APIでできるとか)

東証一部上場企業の銘柄コードを取得して辞書に入れる(python)


ossanengineer.hatenablog.com
これで宣言した宿題をやってみました。
意外と簡単にできたので、備忘録として公開します。

エクセルの場所

www.jpx.co.jp
ここにありました。エクセルファイルがありましたので、ダウンロードしてjupyter nootbookにアップロードしました

ソースコード

import pandas as pd
#東証一部上場企業の銘柄コードエクセルを読み込む
df = pd.read_excel('./data_j.xls')

 #コードの空リストを作って、コードの中身を1次元配列に転写
chord = []
for x in range(len(df.コード)):
    chord.append(int(df.コード[x]))

 #銘柄の空リストを作って、銘柄の中身を1次元配列に転写
meigara = []
for x in range(len(df.銘柄名)):
    meigara.append(str(df.銘柄名[x]))
#コード:銘柄のリストの辞書を作ってみる
meigara_chord = {}
for x in range(len(chord)):
    meigara_chord[chord[x]] = str(meigara[x]) 
#銘柄コード1321を出してみる
print (meigara_chord[1321])

結果出力

import pprint

を入力して、

pprint.pprint(meigara_chord)

と出力してみますと、
f:id:orshibuya0926:20210111171104p:plain
こんな風にきちんと辞書に入り込んでいることが確認することができました。

使い方について

df = pd.read_excel('./data_j.xls')

ここですが、アップロードしたファイルのアドレスを入力してください。

余談

はてなぶろぐでのソースコード出力ですが
>|python|
ソースコード

||<
ソースコードと締めの"||<"の前に一行からの行がないときちんと出力されないらしいです。

株価銘柄の売り時・買い時を判別するプログラム


前書き

以前書いた↓の記事の続きです。
ossanengineer.hatenablog.com
銘柄リストのデータを読み込む =>ボリンジャーバンドのロジックに従って、株の買い時・売り時を判別する
プログラムを書いてみました。
以下、ソースコードです。

ソースコード

from bs4 import BeautifulSoup
import pandas as pd
import requests
from datetime import datetime
import numpy as np
import matplotlib.pyplot as plt
from statistics import mean

#単純に現在の株価がボリンジャーバンドのどのラインにいるのかを判別
def hanbetsu(stock_number,owarine,sma25,std):
    print ("-----")
    print ("銘柄",stock_number,"の買い時を判別します\n結果:\n")
    if owarine[-1:] > (sma25[-1:]+2*std[-1:]):
        print ("昨日の終値は",owarine[-1],"円でした\n移動平均線+2σの値は", int(sma25[-1:]+2*std[-1:]),"円でした")
        print ("この株は上昇トレンドです。買い時です\n逆張りするなら売り時です\n")
    elif owarine[-1:] < (sma25[-1:]-2*std[-1:]):
        print ("昨日の終値は",owarine[-1],"円でした\n移動平均線+2σの値は", int(sma25[-1:]-2*std[-1:]),"円でした")
        print ("この株は下降トレンドです。売り時です\n逆張りするなら買い時です\n")
    else:
        print ("この株は買い時でも、売り時でもありません")
    print ("-----")

def kabu(stock_number):
    url = 'https://kabuoji3.com/stock/{}/'.format(stock_number)
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"}
    soup = BeautifulSoup(requests.get(url,headers = headers).content,'html.parser')

    tag_tr = soup.find_all('tr')
    head = [h.text for h in tag_tr[0].find_all('th')]
    #テーブルのヘッドの取得
    #テーブルの各データの取得
    data = []
    for i in range(1,len(tag_tr)):
        data.append([d.text for d in tag_tr[i].find_all('td')])
        df = pd.DataFrame(data, columns = head)
                #終値と日付を抜き出す
    owarine = []
    day = []
    #dfの要素をリストに転換させる, try~exceptで余計な文字列はフィルタリングできている
    for x in range(len(df['終値'])):
        try:
            owarine.append(int(df.終値[x]))
            day.append(str(df.日付[x]))
        except:
            continue
    #データの日付が古い順から新しい方向に逆転させる
    owarine.reverse()
    day.reverse()

    sma5 = []
    day_sma5 = day[4:]
    for x in range(len(owarine)):
        if (x-4) >= 0:
            sma5 = np.append(sma5,mean(owarine[(x-4):x]))
        else:
            continue
    #25日移動平均線と標準偏差の算出
    sma25 = []
    day_sma25 = day[24:]
    std=[]

    for x in range(len(owarine)):
        if (x-24) >= 0:
            sma25 = np.append(sma25,mean(owarine[(x-24):x]))
            std = np.append(std,np.std(owarine[(x-24):x]))
        else:
            continue
    hanbetsu(stock_number,owarine,sma25,std)

#銘柄リストを作って読み込む
#1321 = NEXT FUNDS 日経225連動型上場投信
#1570 = NEXT日経平均レバレッジ
#8591 = オリックス
meigara = [1321,1570, 8591]
for x in meigara:
    kabu(x)

実行結果

例えば、1321(NEXT FUNDS 日経225連動型上場投信)のデータを読み込ませると、
f:id:orshibuya0926:20210111081046p:plain
こんな感じで出力されます。
例えば、自分が気になる銘柄がある場合、
meigara = [1321,1570, 8591]
このように変えると、
f:id:orshibuya0926:20210111081248p:plain
出力してくれます。

自分が気になっている銘柄が買い時なのかいちいちチャートを巡回するのはめんどくさいですよね。
こんな風に楽できるのもプログラムの力かなぁとは思います。

次の課題

  • CSVファイルから銘柄コードを抽出して、銘柄名を取得する。↑のプログラムに銘柄名を追加させたい。
  • 一目均衡表で判別するプログラムを書いてみる

ボリンジャーバンド付きの株価チャートを書くプログラム(Python)

 


Pythonを使って、株価チャートを書く練習をしてみました。 表題の通り、ボリンジャーバンドまでかけれるようにしてみました。 意外と単純にできたので、備忘録として公開します。まぁ、大したプログラムではないのですが。

ソースコード

from bs4 import BeautifulSoup
import pandas as pd
import requests
from datetime import datetime
import numpy as np
import matplotlib.pyplot as plt
from statistics import mean

y = 2020 #2019年
stock_number = 1321 #日経225連動型上場投信
url = 'https://kabuoji3.com/stock/{}/{}/'.format(stock_number,y)
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"}
soup = BeautifulSoup(requests.get(url,headers = headers).content,'html.parser')

tag_tr = soup.find_all('tr')
head = [h.text for h in tag_tr[0].find_all('th')] #テーブルのヘッドの取得

#テーブルの各データの取得
data = []
for i in range(1,len(tag_tr)):
    data.append([d.text for d in tag_tr[i].find_all('td')])
    df = pd.DataFrame(data, columns = head)
#終値と日付を抜き出す
owarine =df['終値']
day = df['日付']

#終値の整数の変換ができた
for x in range(len(owarine)):
    owarine[x] = int(owarine[x]) 
#移動平均線を書いてみる
#まずは5日移動平均線
sma5 = []
day_sma5 = day[4:]
for x in range(len(owarine)):
    if (x-4) >= 0:
        sma5 = np.append(sma5,mean(owarine[(x-4):x]))
    else:
        continue

#25日移動平均線と標準偏差の算出
sma25 = []
day_sma25 = day[24:]
std=[]

for x in range(len(owarine)):
    if (x-24) >= 0:
        sma25 = np.append(sma25,mean(owarine[(x-24):x]))
        std = np.append(std,np.std(owarine[(x-24):x]))
    else:
        continue
plt.plot(day, owarine, label='raw data',linestyle="--", color='slateblue')
plt.plot(day_sma5,sma5,label ="5 days SMA")
plt.plot(day_sma25,sma25, label ="25 day SMA")
plt.plot(day_sma25,sma25+std, label="+sgm")
plt.plot(day_sma25,sma25+2*std,label="+2sgm")
plt.plot(day_sma25,sma25-std,label="-sgm")
plt.plot(day_sma25,sma25-2*std,label="-2sgm")
plt.title(str(stock_number)+" share value")
plt.legend(loc='lower right')
plt.show()

これを出力すると、次の画像のようになります。横軸汚いのは勘弁してください。
f:id:orshibuya0926:20210104182534p:plain

使い方、いじり方

stock_numberを変えるとほかの銘柄のグラフを出力をさせることができます。
例えば、stock_number = 9983 (ファーストリテイリングユニクロ)と変更しますと、
f:id:orshibuya0926:20210104183027p:plain
こんな感じで出力できます。

y =2020から2019に変更しますと、2019年の株価を出力させることできます。

例えば、125日移動曲線を作りたかったら、

sma125 = []
day_sma125 = day[124:]
for x in range(len(owarine)):
    if (x-125) >= 0:
        sma125 = np.append(sma125,mean(owarine[(x-124):x]))
    else:
        continue

を追加しまして、

plt.plot(day_sma125,sma125,label="125 days SMA")

と入れればグラフに追加できます。

次のステップ

一般的には2σラインを株価が抜けると上昇トレンド発生して買い時、-2σラインを株価が抜けると下降トレンドが発生して売り時と判断できます。

  • 一目均衡表をグラフに追加して、昨日の株価が売り時か買い時かを返してくれるプログラムを作る

"べつに、チャートで見て自分で判断すればいいじゃん"と言われれば、それまでですが、チャートを見て株を買うときに心理的な要素を排除したいがために作成しております。
ボリンジャーバンドに従ってやり取りしてみた、というネタでブログを書いてみたいという欲望もあります。

あらしの森プレイログ(86階で死亡)

あらしの森のプレイログを書きます。
結果ですが、タイトル通り86階で死にました。76階ぐらいからlv超過モンスター (例~ 2)がわんさか出てくるので即死にます。ガチるのはほとんど無理です。


~4階まで

私の定石攻略通り、3階で風が吹くまで粘りました。
敵のドロップからハラモチの盾ゲットしましたので、ここぞとばかりに粘ります。
ドロップアイテムとして、真空切りの巻物をゲットしたので4階で即読み=>アイテム回収することができました。

4階突入時のアイテム欄がこんな感じです。

f:id:orshibuya0926:20210102062330j:plain


~24階まで

 4階でおねむガラガラがゲットできましたので、メイン武器にしました。
そのほかにも反撃の盾、かまいたちなどもゲットできましたので滑り出しは順調です。
4階ではアイテム回収後、風が吹くまで粘りました。畠荒らしが出てきたら、直線上にうろうろして雑草をはずしてくれるまで待ちます。2体以上荒らしが出てきたら1体は片づけます。ひたすらこれを繰り返しまして、アイテムドロップと武器の成長、シレンの覚醒を狙います。


5階~7階ぐらいから草鳥が出てくるので、草をかき集めます。
ハラモチの盾があるので、風が吹くまで粘ります。以降、14階まではひたすら稼ぎます。

13階前後でぬすっとどが出てきますので、これも狩りまくります。
たまに超不幸の種、天使の種といったレアアイテムがゲットできますので、回収できるとベストです。大抵石しか手に入りませんが、ダンジョンの性質上次のような雑草部屋をつくれば稼ぎが安定します。

f:id:orshibuya0926:20210102063321p:plain

 

14階ではトドが出るので気合を入れて稼ぎまくります。

15-18階でマゼルン合成。貯めた草、装備をガンガン武器・盾に突っ込んでいきます。風が吹くまで粘る作戦のため、武器に印入れたい放題です。

19 ~ 23階ぐらいから水マップになって、ミドロ・めまわし大根に襲われます。
ミドロは装備を脱いで対応。通路で鉢合わせの場合はアイテムを惜しまず使って処理します。
大根はこんらんよけの腕輪があればそれだけで完封できますが、ない場合は階段即おりで対処します。

24階でもトドが出ますので、20~ 23階で即おりしてもカバーすることができます。
24階突破時のアイテムはこんな感じでした。

f:id:orshibuya0926:20210102064250p:plain

 


 ~63階まで

25階でもトドが出ますので、トド狩り続行します。
26-33階までいやがらせなモンスターテーブルが続きます。
ガラ、すいだすゾウ、ウニ、ギャドン等々。
これまで入れてきた印で1~2撃で大抵落とせるフロアと判断したら粘り、厳しいと判断したらアイテム回収しておりします。

それ以降も同じ感じで対処できるはずです。
60-62階にはみだれ大根が出ますので、全力で処理しに行きます。
f:id:orshibuya0926:20210102064507p:plain

f:id:orshibuya0926:20210102061802j:plain

f:id:orshibuya0926:20210102081641p:plain

f:id:orshibuya0926:20210102081705p:plain

小ネタですが、石をばらまいてモンスターの罠を起動させればトド狩りの足しになります。

f:id:orshibuya0926:20210102081357p:plain


 ~73階から死亡まで

ここら辺だともうガチれなくなるので、アイテム回収して即おり決めてました。
74階ははじきよけの腕輪、錠前の盾があればトド狩りができます。
今回は錠前の盾がなかったので、トド狩りはあきらめました。雑草はじきで保存の壺が割られたのが痛かったです。
76階からは即逃げです。通路の角から一発なぐって、睡眠効果が発動したら対処できます。が、シャインバード2が即駆けつけるので鳥が飛んで来たら札で巻き込んで処理するか逃げの2択です。

 

ラビゾーン+ゾウ2のコンボで復活草も尽き、浮遊の腕輪で逃げ回っていたところ鉢合わせして死にました。

f:id:orshibuya0926:20210102082338p:plain

動かずの盾もあり、ラビの対策はできていたはずですが死亡しました。
まだまだですね。

反撃の盾をメインにしたのは超過モンスター対策です。超過モンスターからの被ダメが半端ないのですが、反射ダメージで敵を処理することもできます。

超不幸の種を盾に入れれば、ダメージ反射で1ターンキルできると思ったのですが、
敵からのダメージ反射 => 超不幸の効果という順番で発動するので、思った通りにはいかなかったです。

 

なんとか2021年までにはクリアしたいものですね。

 

プログラミングを使って自動検索させる

前置き

某楽〇のサイトを使っていますと、
"web検索30回でポイント山分け!"
というのを見かけますが、30回も検索するのめんどくさいですよね。
実際やってみると10回ぐらいでネタ切れになります。
そこで、プログラミングの力を使って自動化させてみました。
使用言語はpythonです。ソースコードは次に公開しています。
私は情報系でも何でもないので、プログラムの書き方の作法とか特に知らんです。

ソースコード

import pyautogui as pg
import time
import random
def kensaku():
    #timeは検索回数を決める変数、numは~GBの~を決める2^n
    times = 35
    num = 2
    
    #lwの中身を検索キーワードにする。この中からランダムに選ばれる。"検索したいきーわーど"を入れる。例、"はてなブログ"
    lw  =[]
    lw_tr = []
    lw_tr2 = []
    
    #実際に検索する場所
    for x in range (times):
        time.sleep(3)
        t = random.random()
        #検索ツールボックスの位置を指定
        pg.moveTo(x=1056, y=375, duration = 3)
        pg.click(x=1056, y=375)
        time.sleep(3)
        
        #乱数で適当に場合分けして、検索が開始される
        if t < 0.3:
            pg.typewrite(random.choice(lw_tr2))
        elif 0.3 < t < 0.5:
            pg.typewrite(random.choice(lw_tr))
        elif 0.5 <t < 0.7:
            pg.typewrite(random.choice(lw)+' '+str(num)+'GB')
        elif 0.7 < t < 0.9:
            pg.typewrite('HDD '+str(num)+'GB')
        else:
            pg.typewrite('SSD '+str(num)+'GB')
        for y in range(2):
            pg.press('enter')
        num =2*num
        if num == 512:
            num = 2
        time.sleep(4)
        
        #ブラウザの戻る位置を指定してあげる
        pg.moveTo(x=17, y=50,duration = 1)
        time.sleep(2)
        pg.click(x=17, y=50)
        time.sleep(2)
    
    #終わったので終了操作させる
    pg.hotkey('ctrl','w')

使ってみての感想

プログラム走らせて見て、特に問題なく検索ルーティンをこなすことができました。
一日あたり某〇天サイトからは4 ptもらえています。
365日こなしたとすると、4 * 365 = 1460 ptもらえます。
さらに、これをポイント投資にまわして年利5パーセントで20年積み立て運用できたと仮定すると
(サービスが20年続いているという前提付きですが)
複利計算式 a(1-r^n)/(1-r)にa=1460, n = 20, r = 1.05を代入してあげますと、
答え 48180円
になります。まぁ、月々の資産運用の足しにはなりそうですね。

コーヒーメーカーっていいんですかね?

コーヒーの話を書きます。

コーヒーのイラスト「コーヒーメーカーとコーヒーカップ」

 

みそかにアメトークを見ていましたら、家電芸人でツインバードのコーヒーメーカーが特集されていました。

 

f:id:orshibuya0926:20210101112431p:plain

お湯が出てくるところと、挽いたコーヒー豆のドリッパーの間に2㎝の隙間ができて、匂いが広がっていい!美味しいコーヒーが飲める!と紹介されていました。

あ~これいい商品だなぁ、こんなのがあれば素敵な朝を迎えられるだろうな~買っちゃおうかなぁと思っている人、

ちょっと待ってください。

コーヒーの味って何で決まるのか、それはコーヒー豆です。
挽いたコーヒー豆の鮮度と質です。

ピンとこない方、コーヒー豆をお刺身と置き換えるとピンと来るはずです。
いい包丁、いいまな板を買いそろえたとしても刺身のネタ自体がダメだったら刺身はまずいです。
コーヒー淹れる環境を整えても、コーヒー豆自体がまずかったらどうにもなりません。

うまいコーヒー飲みたいなら、通販でスペシャティーコーヒー豆を豆のまま買って、コーヒーミル(3千円)買って、100均でドリッパーとコーヒーフィルターを買えばぶっちゃけ十分です。おいしい豆を売っている会社は2chスレに行けばなんとなく情報を拾えます。

コーヒーの淹れ方を勉強すると、フレンチプレスやら金属フィルターで入れると美味いという話がありますがスルーして構いません。
フレンチプレスは私は試したことがありますが、雰囲気だけです。味はぶっちゃけ違いは判らないです。コーヒーオイルが出る、とかの話がありますがそんなにわかりません。金属フィルターもしかりです。蛇足ですが、ペーパーフィルターがいらない!ゴミも出ないし節約になって素敵!と思いますでしょうが、使ってみたらわかります。粉の処理がひじょーーにめんどくさいです。

話をまとめますと、コーヒーはハンドドリップで十分です。
豆を通販で買う。おいしい豆の情報は2chで拾う。100均と安いコーヒーミルを買いそろえる。
おいしいコーヒーには豆にお金をかけたほうが、かけたお金に対してパフォーマンスはデカいかなぁと思います。